From 0cfa90bcd7f6a35a3b9c50d39b456c31fc1ff18c Mon Sep 17 00:00:00 2001 From: umutdural Date: Wed, 20 Mar 2024 17:09:49 +0100 Subject: [PATCH 01/25] vscode-extension: extension scaffold --- .cargo/config.toml | 5 + .gitignore | 3 +- Cargo.lock | 87 +- Cargo.toml | 8 + caesar-ext/.eslintrc.json | 30 + caesar-ext/.vscode-test.mjs | 5 + caesar-ext/.vscode/extensions.json | 8 + caesar-ext/.vscode/launch.json | 21 + caesar-ext/.vscode/settings.json | 11 + caesar-ext/.vscode/tasks.json | 20 + caesar-ext/.vscodeignore | 11 + caesar-ext/CHANGELOG.md | 9 + caesar-ext/README.md | 71 + caesar-ext/out/extension.js | 88 + caesar-ext/out/extension.js.map | 1 + caesar-ext/out/test/extension.test.js | 38 + caesar-ext/out/test/extension.test.js.map | 1 + caesar-ext/package-lock.json | 3027 +++++++++++++++++++ caesar-ext/package.json | 41 + caesar-ext/src/extension.ts | 72 + caesar-ext/src/test/extension.test.ts | 15 + caesar-ext/tsconfig.json | 17 + caesar-ext/vsc-extension-quickstart.md | 43 + src/driver.rs | 284 +- src/language_server/language_server_main.rs | 161 + src/language_server/mod.rs | 1 + src/main.rs | 118 +- vscode-ext/package-lock.json | 470 +++ vscode-ext/package.json | 50 +- vscode-ext/src/extension.ts | 26 + 30 files changed, 4602 insertions(+), 140 deletions(-) create mode 100644 .cargo/config.toml create mode 100644 caesar-ext/.eslintrc.json create mode 100644 caesar-ext/.vscode-test.mjs create mode 100644 caesar-ext/.vscode/extensions.json create mode 100644 caesar-ext/.vscode/launch.json create mode 100644 caesar-ext/.vscode/settings.json create mode 100644 caesar-ext/.vscode/tasks.json create mode 100644 caesar-ext/.vscodeignore create mode 100644 caesar-ext/CHANGELOG.md create mode 100644 caesar-ext/README.md create mode 100644 caesar-ext/out/extension.js create mode 100644 caesar-ext/out/extension.js.map create mode 100644 caesar-ext/out/test/extension.test.js create mode 100644 caesar-ext/out/test/extension.test.js.map create mode 100644 caesar-ext/package-lock.json create mode 100644 caesar-ext/package.json create mode 100644 caesar-ext/src/extension.ts create mode 100644 caesar-ext/src/test/extension.test.ts create mode 100644 caesar-ext/tsconfig.json create mode 100644 caesar-ext/vsc-extension-quickstart.md create mode 100644 src/language_server/language_server_main.rs create mode 100644 src/language_server/mod.rs create mode 100644 vscode-ext/package-lock.json create mode 100644 vscode-ext/src/extension.ts diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..359ae44 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,5 @@ +[target.x86_64-unknown-linux-gnu] +rustflags = [ + "-C", "link-arg=-fuse-ld=lld", +] + diff --git a/.gitignore b/.gitignore index 5a9016f..d48711d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ target .DS_Store benchmark-results.csv - +vscode-ext/node_modules/ +node_modules/ # .dockerignore is symlinked to the .gitignore, so this line is useful: .git diff --git a/Cargo.lock b/Cargo.lock index 404ffbd..49868ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -202,6 +202,8 @@ dependencies = [ "lalrpop", "lalrpop-util", "lit", + "lsp-server", + "lsp-types", "memchr", "num", "once_cell", @@ -211,6 +213,8 @@ dependencies = [ "proptest", "ref-cast", "replace_with", + "serde", + "serde_json", "shellwords", "simple-process-stats", "string-interner", @@ -380,22 +384,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.7" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" +checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" dependencies = [ - "cfg-if 1.0.0", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" -dependencies = [ - "cfg-if 1.0.0", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crunchy" @@ -448,7 +448,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.10", + "syn 2.0.52", ] [[package]] @@ -465,7 +465,7 @@ checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.10", + "syn 2.0.52", ] [[package]] @@ -1062,6 +1062,31 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "lsp-server" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248f65b78f6db5d8e1b1604b4098a28b43d21a8eb1deeca22b1c421b276c7095" +dependencies = [ + "crossbeam-channel", + "log", + "serde", + "serde_json", +] + +[[package]] +name = "lsp-types" +version = "0.95.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "158c1911354ef73e8fe42da6b10c0484cb65c7f1007f28022e847706c1ab6984" +dependencies = [ + "bitflags", + "serde", + "serde_json", + "serde_repr", + "url", +] + [[package]] name = "matchers" version = "0.1.0" @@ -1383,9 +1408,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.53" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -1440,9 +1465,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quote" -version = "1.0.26" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -1532,7 +1557,7 @@ checksum = "8d2275aab483050ab2a7364c1a46604865ee7d6906684e08db0f090acf74f9e7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.10", + "syn 2.0.52", ] [[package]] @@ -1660,35 +1685,46 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.158" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.158" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.10", + "syn 2.0.52", ] [[package]] name = "serde_json" -version = "1.0.94" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0a21fba416426ac927b1691996e82079f8b6156e920c85345f135b2e9ba2de" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "sharded-slab" version = "0.1.4" @@ -1829,9 +1865,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.10" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aad1363ed6d37b84299588d62d3a7d95b5a5c2d9aad5c85609fda12afaa1f40" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", @@ -1907,7 +1943,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.10", + "syn 2.0.52", ] [[package]] @@ -2129,6 +2165,7 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index c115f2f..def7aaf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,6 +48,10 @@ z3rro = { path = "./z3rro" } dashmap = "5.4" im-rc = "15.1.0" cfg-if = "1.0.0" +lsp-types = "0.95.0" +serde_json = "1.0.114" +lsp-server = "0.7.6" +serde = "1.0.197" [build-dependencies] lalrpop = "0.19" @@ -65,6 +69,10 @@ name = "integration" path = "tests/integration.rs" harness = false +[profile.dev] +lto = false +# debug = false + [profile.release] # Debug information is nice, but it increases the binary size by about 500 megabytes. # So we don't enable it for release builds. diff --git a/caesar-ext/.eslintrc.json b/caesar-ext/.eslintrc.json new file mode 100644 index 0000000..86c86f3 --- /dev/null +++ b/caesar-ext/.eslintrc.json @@ -0,0 +1,30 @@ +{ + "root": true, + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 6, + "sourceType": "module" + }, + "plugins": [ + "@typescript-eslint" + ], + "rules": { + "@typescript-eslint/naming-convention": [ + "warn", + { + "selector": "import", + "format": [ "camelCase", "PascalCase" ] + } + ], + "@typescript-eslint/semi": "warn", + "curly": "warn", + "eqeqeq": "warn", + "no-throw-literal": "warn", + "semi": "off" + }, + "ignorePatterns": [ + "out", + "dist", + "**/*.d.ts" + ] +} \ No newline at end of file diff --git a/caesar-ext/.vscode-test.mjs b/caesar-ext/.vscode-test.mjs new file mode 100644 index 0000000..b62ba25 --- /dev/null +++ b/caesar-ext/.vscode-test.mjs @@ -0,0 +1,5 @@ +import { defineConfig } from '@vscode/test-cli'; + +export default defineConfig({ + files: 'out/test/**/*.test.js', +}); diff --git a/caesar-ext/.vscode/extensions.json b/caesar-ext/.vscode/extensions.json new file mode 100644 index 0000000..db70f88 --- /dev/null +++ b/caesar-ext/.vscode/extensions.json @@ -0,0 +1,8 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "dbaeumer.vscode-eslint", + "ms-vscode.extension-test-runner" + ] +} diff --git a/caesar-ext/.vscode/launch.json b/caesar-ext/.vscode/launch.json new file mode 100644 index 0000000..8880465 --- /dev/null +++ b/caesar-ext/.vscode/launch.json @@ -0,0 +1,21 @@ +// A launch configuration that compiles the extension and then opens it inside a new window +// Use IntelliSense to learn about possible attributes. +// Hover to view descriptions of existing attributes. +// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Run Extension", + "type": "extensionHost", + "request": "launch", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}" + ], + "outFiles": [ + "${workspaceFolder}/out/**/*.js" + ], + "preLaunchTask": "${defaultBuildTask}" + } + ] +} diff --git a/caesar-ext/.vscode/settings.json b/caesar-ext/.vscode/settings.json new file mode 100644 index 0000000..30bf8c2 --- /dev/null +++ b/caesar-ext/.vscode/settings.json @@ -0,0 +1,11 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.exclude": { + "out": false // set this to true to hide the "out" folder with the compiled JS files + }, + "search.exclude": { + "out": true // set this to false to include "out" folder in search results + }, + // Turn off tsc task auto detection since we have the necessary tasks as npm scripts + "typescript.tsc.autoDetect": "off" +} \ No newline at end of file diff --git a/caesar-ext/.vscode/tasks.json b/caesar-ext/.vscode/tasks.json new file mode 100644 index 0000000..3b17e53 --- /dev/null +++ b/caesar-ext/.vscode/tasks.json @@ -0,0 +1,20 @@ +// See https://go.microsoft.com/fwlink/?LinkId=733558 +// for the documentation about the tasks.json format +{ + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "watch", + "problemMatcher": "$tsc-watch", + "isBackground": true, + "presentation": { + "reveal": "never" + }, + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} diff --git a/caesar-ext/.vscodeignore b/caesar-ext/.vscodeignore new file mode 100644 index 0000000..72aa0fe --- /dev/null +++ b/caesar-ext/.vscodeignore @@ -0,0 +1,11 @@ +.vscode/** +.vscode-test/** +src/** +.gitignore +.yarnrc +vsc-extension-quickstart.md +**/tsconfig.json +**/.eslintrc.json +**/*.map +**/*.ts +**/.vscode-test.* diff --git a/caesar-ext/CHANGELOG.md b/caesar-ext/CHANGELOG.md new file mode 100644 index 0000000..0421b91 --- /dev/null +++ b/caesar-ext/CHANGELOG.md @@ -0,0 +1,9 @@ +# Change Log + +All notable changes to the "caesar" extension will be documented in this file. + +Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. + +## [Unreleased] + +- Initial release \ No newline at end of file diff --git a/caesar-ext/README.md b/caesar-ext/README.md new file mode 100644 index 0000000..61adf17 --- /dev/null +++ b/caesar-ext/README.md @@ -0,0 +1,71 @@ +# caesar README + +This is the README for your extension "caesar". After writing up a brief description, we recommend including the following sections. + +## Features + +Describe specific features of your extension including screenshots of your extension in action. Image paths are relative to this README file. + +For example if there is an image subfolder under your extension project workspace: + +\!\[feature X\]\(images/feature-x.png\) + +> Tip: Many popular extensions utilize animations. This is an excellent way to show off your extension! We recommend short, focused animations that are easy to follow. + +## Requirements + +If you have any requirements or dependencies, add a section describing those and how to install and configure them. + +## Extension Settings + +Include if your extension adds any VS Code settings through the `contributes.configuration` extension point. + +For example: + +This extension contributes the following settings: + +* `myExtension.enable`: Enable/disable this extension. +* `myExtension.thing`: Set to `blah` to do something. + +## Known Issues + +Calling out known issues can help limit users opening duplicate issues against your extension. + +## Release Notes + +Users appreciate release notes as you update your extension. + +### 1.0.0 + +Initial release of ... + +### 1.0.1 + +Fixed issue #. + +### 1.1.0 + +Added features X, Y, and Z. + +--- + +## Following extension guidelines + +Ensure that you've read through the extensions guidelines and follow the best practices for creating your extension. + +* [Extension Guidelines](https://code.visualstudio.com/api/references/extension-guidelines) + +## Working with Markdown + +You can author your README using Visual Studio Code. Here are some useful editor keyboard shortcuts: + +* Split the editor (`Cmd+\` on macOS or `Ctrl+\` on Windows and Linux). +* Toggle preview (`Shift+Cmd+V` on macOS or `Shift+Ctrl+V` on Windows and Linux). +* Press `Ctrl+Space` (Windows, Linux, macOS) to see a list of Markdown snippets. + +## For more information + +* [Visual Studio Code's Markdown Support](http://code.visualstudio.com/docs/languages/markdown) +* [Markdown Syntax Reference](https://help.github.com/articles/markdown-basics/) + +**Enjoy!** diff --git a/caesar-ext/out/extension.js b/caesar-ext/out/extension.js new file mode 100644 index 0000000..8b93a5f --- /dev/null +++ b/caesar-ext/out/extension.js @@ -0,0 +1,88 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.deactivate = exports.activate = void 0; +// The module 'vscode' contains the VS Code extensibility API +// Import the module and reference it with the alias vscode in your code below +const vscode = __importStar(require("vscode")); +// This method is called when your extension is activated +// Your extension is activated the very first time the command is executed +function activate(context) { + let decorationType = vscode.window.createTextEditorDecorationType({ + after: { + color: new vscode.ThemeColor('editor.foreground'), + backgroundColor: new vscode.ThemeColor('editor.background'), + }, + }); + let editor = vscode.window.activeTextEditor; + if (editor) { + updateDecorations(editor, decorationType); + } + vscode.workspace.onWillSaveTextDocument(event => { + const openEditor = vscode.window.visibleTextEditors.filter(editor => editor.document.uri === event.document.uri)[0]; + updateDecorations(openEditor, decorationType); + }); + // Use the console to output diagnostic information (console.log) and errors (console.error) + // This line of code will only be executed once when your extension is activated + console.log('Congratulations, your extension "caesar" is now active!'); + // The command has been defined in the package.json file + // Now provide the implementation of the command with registerCommand + // The commandId parameter must match the command field in package.json + let disposable = vscode.commands.registerCommand('caesar.helloWorld', () => { + // The code you place here will be executed every time your command is executed + // Display a message box to the user + vscode.window.showInformationMessage('Hello World from caesar!!!!'); + }); + context.subscriptions.push(disposable); +} +exports.activate = activate; +// This method is called when your extension is deactivated +function deactivate() { } +exports.deactivate = deactivate; +function updateDecorations(editor, decorationType) { + const decorations = []; + const procedures = [new vscode.Position(0, 0)]; + // Assuming `procedures` is an array of procedure positions + for (const position of procedures) { + const verified = isVerified(editor.document, position); + const range = new vscode.Range(position, position.translate(0, 0)); + const decoration = { + range, + renderOptions: { + after: { + contentText: verified ? '✔️' : '❌', + color: new vscode.ThemeColor('editor.foreground'), + }, + }, + }; + decorations.push(decoration); + } + editor.setDecorations(decorationType, decorations); +} +function isVerified(document, position) { + // Implement logic to determine if the procedure at the given position is verified + return true; // Return true if verified, false otherwise +} +//# sourceMappingURL=extension.js.map \ No newline at end of file diff --git a/caesar-ext/out/extension.js.map b/caesar-ext/out/extension.js.map new file mode 100644 index 0000000..a3c4895 --- /dev/null +++ b/caesar-ext/out/extension.js.map @@ -0,0 +1 @@ +{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6DAA6D;AAC7D,8EAA8E;AAC9E,+CAAiC;AAEjC,yDAAyD;AACzD,0EAA0E;AAC1E,SAAgB,QAAQ,CAAC,OAAgC;IAGxD,IAAI,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,8BAA8B,CAAC;QACjE,KAAK,EAAE;YACN,KAAK,EAAE,IAAI,MAAM,CAAC,UAAU,CAAC,mBAAmB,CAAC;YACjD,eAAe,EAAE,IAAI,MAAM,CAAC,UAAU,CAAC,mBAAmB,CAAC;SAC3D;KACD,CAAC,CAAC;IAEH,IAAI,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC;IAC5C,IAAI,MAAM,EAAE,CAAC;QACZ,iBAAiB,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,CAAC,SAAS,CAAC,sBAAsB,CAAC,KAAK,CAAC,EAAE;QAC/C,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,MAAM,CACzD,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,KAAK,KAAK,CAAC,QAAQ,CAAC,GAAG,CACpD,CAAC,CAAC,CAAC,CAAA;QACJ,iBAAiB,CAAC,UAAU,EAAE,cAAc,CAAC,CAAA;IAC9C,CAAC,CAAC,CAAA;IAEF,4FAA4F;IAC5F,gFAAgF;IAChF,OAAO,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;IAEvE,wDAAwD;IACxD,qEAAqE;IACrE,uEAAuE;IACvE,IAAI,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC1E,+EAA+E;QAC/E,oCAAoC;QACpC,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,6BAA6B,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AACxC,CAAC;AApCD,4BAoCC;AAED,2DAA2D;AAC3D,SAAgB,UAAU,KAAK,CAAC;AAAhC,gCAAgC;AAEhC,SAAS,iBAAiB,CAAC,MAAyB,EAAE,cAA+C;IACpG,MAAM,WAAW,GAA+B,EAAE,CAAC;IACnD,MAAM,UAAU,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/C,2DAA2D;IAC3D,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACvD,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACnE,MAAM,UAAU,GAAG;YAClB,KAAK;YACL,aAAa,EAAE;gBACd,KAAK,EAAE;oBACN,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG;oBAClC,KAAK,EAAE,IAAI,MAAM,CAAC,UAAU,CAAC,mBAAmB,CAAC;iBACjD;aACD;SACD,CAAC;QACF,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9B,CAAC;IACD,MAAM,CAAC,cAAc,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;AACpD,CAAC;AAED,SAAS,UAAU,CAAC,QAA6B,EAAE,QAAyB;IAC3E,kFAAkF;IAClF,OAAO,IAAI,CAAC,CAAC,2CAA2C;AACzD,CAAC"} \ No newline at end of file diff --git a/caesar-ext/out/test/extension.test.js b/caesar-ext/out/test/extension.test.js new file mode 100644 index 0000000..04257df --- /dev/null +++ b/caesar-ext/out/test/extension.test.js @@ -0,0 +1,38 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const assert = __importStar(require("assert")); +// You can import and use all API from the 'vscode' module +// as well as import your extension to test it +const vscode = __importStar(require("vscode")); +// import * as myExtension from '../../extension'; +suite('Extension Test Suite', () => { + vscode.window.showInformationMessage('Start all tests.'); + test('Sample test', () => { + assert.strictEqual(-1, [1, 2, 3].indexOf(5)); + assert.strictEqual(-1, [1, 2, 3].indexOf(0)); + }); +}); +//# sourceMappingURL=extension.test.js.map \ No newline at end of file diff --git a/caesar-ext/out/test/extension.test.js.map b/caesar-ext/out/test/extension.test.js.map new file mode 100644 index 0000000..5fe9345 --- /dev/null +++ b/caesar-ext/out/test/extension.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"extension.test.js","sourceRoot":"","sources":["../../src/test/extension.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAAiC;AAEjC,0DAA0D;AAC1D,8CAA8C;AAC9C,+CAAiC;AACjC,kDAAkD;AAElD,KAAK,CAAC,sBAAsB,EAAE,GAAG,EAAE;IAClC,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,kBAAkB,CAAC,CAAC;IAEzD,IAAI,CAAC,aAAa,EAAE,GAAG,EAAE;QACxB,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7C,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/caesar-ext/package-lock.json b/caesar-ext/package-lock.json new file mode 100644 index 0000000..200e007 --- /dev/null +++ b/caesar-ext/package-lock.json @@ -0,0 +1,3027 @@ +{ + "name": "caesar", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "caesar", + "version": "0.0.1", + "devDependencies": { + "@types/mocha": "^10.0.6", + "@types/node": "18.x", + "@types/vscode": "^1.87.0", + "@typescript-eslint/eslint-plugin": "^7.0.2", + "@typescript-eslint/parser": "^7.0.2", + "@vscode/test-cli": "^0.0.6", + "@vscode/test-electron": "^2.3.9", + "eslint": "^8.56.0", + "typescript": "^5.3.3" + }, + "engines": { + "vscode": "^1.87.0" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/mocha": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", + "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.19.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.21.tgz", + "integrity": "sha512-2Q2NeB6BmiTFQi4DHBzncSoq/cJMLDdhPaAoJFnFCyD9a8VPZRf7a1GAwp1Edb7ROaZc5Jz/tnZyL6EsWMRaqw==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true + }, + "node_modules/@types/vscode": { + "version": "1.87.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.87.0.tgz", + "integrity": "sha512-y3yYJV2esWr8LNjp3VNbSMWG7Y43jC8pCldG8YwiHGAQbsymkkMMt0aDT1xZIOFM2eFcNiUc+dJMx1+Z0UT8fg==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.1.tgz", + "integrity": "sha512-zioDz623d0RHNhvx0eesUmGfIjzrk18nSBC8xewepKXbBvN/7c1qImV7Hg8TI1URTxKax7/zxfxj3Uph8Chcuw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/type-utils": "7.1.1", + "@typescript-eslint/utils": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.1.tgz", + "integrity": "sha512-ZWUFyL0z04R1nAEgr9e79YtV5LbafdOtN7yapNbn1ansMyaegl2D4bL7vHoJ4HPSc4CaLwuCVas8CVuneKzplQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/typescript-estree": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", + "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.1.tgz", + "integrity": "sha512-5r4RKze6XHEEhlZnJtR3GYeCh1IueUHdbrukV2KSlLXaTjuSfeVF8mZUVPLovidCuZfbVjfhi4c0DNSa/Rdg5g==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.1.1", + "@typescript-eslint/utils": "7.1.1", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", + "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", + "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.1.tgz", + "integrity": "sha512-thOXM89xA03xAE0lW7alstvnyoBUbBX38YtY+zAUcpRPcq9EIhXPuJ0YTv948MbzmKh6e1AUszn5cBFK49Umqg==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/typescript-estree": "7.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", + "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.1.1", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@vscode/test-cli": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@vscode/test-cli/-/test-cli-0.0.6.tgz", + "integrity": "sha512-4i61OUv5PQr3GxhHOuUgHdgBDfIO/kXTPCsEyFiMaY4SOqQTgkTmyZLagHehjOgCfsXdcrJa3zgQ7zoc+Dh6hQ==", + "dev": true, + "dependencies": { + "@types/mocha": "^10.0.2", + "c8": "^9.1.0", + "chokidar": "^3.5.3", + "enhanced-resolve": "^5.15.0", + "glob": "^10.3.10", + "minimatch": "^9.0.3", + "mocha": "^10.2.0", + "supports-color": "^9.4.0", + "yargs": "^17.7.2" + }, + "bin": { + "vscode-test": "out/bin.mjs" + } + }, + "node_modules/@vscode/test-electron": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.9.tgz", + "integrity": "sha512-z3eiChaCQXMqBnk2aHHSEkobmC2VRalFQN0ApOAtydL172zXGxTwGrRtviT5HnUB+Q+G3vtEYFtuQkYqBzYgMA==", + "dev": true, + "dependencies": { + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "jszip": "^3.10.1", + "semver": "^7.5.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/c8": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/c8/-/c8-9.1.0.tgz", + "integrity": "sha512-mBWcT5iqNir1zIkzSPyI3NCR9EZCVI3WUD+AVO17MVWTSFNyUueXE82qTeampNtTr+ilN/5Ua3j24LgbCKjDVg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@istanbuljs/schema": "^0.1.3", + "find-up": "^5.0.0", + "foreground-child": "^3.1.1", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.1.6", + "test-exclude": "^6.0.0", + "v8-to-istanbul": "^9.0.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1" + }, + "bin": { + "c8": "bin/c8.js" + }, + "engines": { + "node": ">=14.14.0" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/enhanced-resolve": { + "version": "5.15.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.1.tgz", + "integrity": "sha512-3d3JRbwsCLJsYgvb6NuWEG44jjPSOMuS73L/6+7BZuoKm3W+qXnSoIYVHi8dG7Qcg4inAY4jbzkZ7MnskePeDg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dev": true, + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mocha": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.3.0.tgz", + "integrity": "sha512-uF2XJs+7xSLsrmIvn37i/wnc91nw7XjOQB8ccyx5aEgdnohr7n+rEiZP23WkCYHjilR6+EboEnbq/ZQDz4LSbg==", + "dev": true, + "dependencies": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "8.1.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/mocha/node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/mocha/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/mocha/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/mocha/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/mocha/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/mocha/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", + "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/v8-to-istanbul": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/workerpool": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/caesar-ext/package.json b/caesar-ext/package.json new file mode 100644 index 0000000..ce806b5 --- /dev/null +++ b/caesar-ext/package.json @@ -0,0 +1,41 @@ +{ + "name": "caesar", + "displayName": "caesar", + "description": "VSCode Extension of the Deductive Probabilistic Program Verifier Caesar", + "version": "0.0.1", + "engines": { + "vscode": "^1.87.0" + }, + "categories": [ + "Other" + ], + "activationEvents": [], + "main": "./out/extension.js", + "contributes": { + "commands": [ + { + "command": "caesar.helloWorld", + "title": "Hello World" + } + ] + }, + "scripts": { + "vscode:prepublish": "npm run compile", + "compile": "tsc -p ./", + "watch": "tsc -watch -p ./", + "pretest": "npm run compile && npm run lint", + "lint": "eslint src --ext ts", + "test": "vscode-test" + }, + "devDependencies": { + "@types/vscode": "^1.87.0", + "@types/mocha": "^10.0.6", + "@types/node": "18.x", + "@typescript-eslint/eslint-plugin": "^7.0.2", + "@typescript-eslint/parser": "^7.0.2", + "eslint": "^8.56.0", + "typescript": "^5.3.3", + "@vscode/test-cli": "^0.0.6", + "@vscode/test-electron": "^2.3.9" + } +} diff --git a/caesar-ext/src/extension.ts b/caesar-ext/src/extension.ts new file mode 100644 index 0000000..c0b1802 --- /dev/null +++ b/caesar-ext/src/extension.ts @@ -0,0 +1,72 @@ +// The module 'vscode' contains the VS Code extensibility API +// Import the module and reference it with the alias vscode in your code below +import * as vscode from 'vscode'; + +// This method is called when your extension is activated +// Your extension is activated the very first time the command is executed +export function activate(context: vscode.ExtensionContext) { + + + let decorationType = vscode.window.createTextEditorDecorationType({ + after: { + color: new vscode.ThemeColor('editor.foreground'), + backgroundColor: new vscode.ThemeColor('editor.background'), + }, + }); + + let editor = vscode.window.activeTextEditor; + if (editor) { + updateDecorations(editor, decorationType); + } + + vscode.workspace.onWillSaveTextDocument(event => { + const openEditor = vscode.window.visibleTextEditors.filter( + editor => editor.document.uri === event.document.uri + )[0] + updateDecorations(openEditor, decorationType) + }) + + // Use the console to output diagnostic information (console.log) and errors (console.error) + // This line of code will only be executed once when your extension is activated + console.log('Congratulations, your extension "caesar" is now active!'); + + // The command has been defined in the package.json file + // Now provide the implementation of the command with registerCommand + // The commandId parameter must match the command field in package.json + let disposable = vscode.commands.registerCommand('caesar.helloWorld', () => { + // The code you place here will be executed every time your command is executed + // Display a message box to the user + vscode.window.showInformationMessage('Hello World from caesar!!!!'); + }); + + context.subscriptions.push(disposable); +} + +// This method is called when your extension is deactivated +export function deactivate() { } + +function updateDecorations(editor: vscode.TextEditor, decorationType: vscode.TextEditorDecorationType) { + const decorations: vscode.DecorationOptions[] = []; + const procedures = [new vscode.Position(0, 0)]; + // Assuming `procedures` is an array of procedure positions + for (const position of procedures) { + const verified = isVerified(editor.document, position); + const range = new vscode.Range(position, position.translate(0, 0)); + const decoration = { + range, + renderOptions: { + after: { + contentText: verified ? '✔️' : '❌', + color: new vscode.ThemeColor('editor.foreground'), + }, + }, + }; + decorations.push(decoration); + } + editor.setDecorations(decorationType, decorations); +} + +function isVerified(document: vscode.TextDocument, position: vscode.Position): boolean { + // Implement logic to determine if the procedure at the given position is verified + return true; // Return true if verified, false otherwise +} diff --git a/caesar-ext/src/test/extension.test.ts b/caesar-ext/src/test/extension.test.ts new file mode 100644 index 0000000..4ca0ab4 --- /dev/null +++ b/caesar-ext/src/test/extension.test.ts @@ -0,0 +1,15 @@ +import * as assert from 'assert'; + +// You can import and use all API from the 'vscode' module +// as well as import your extension to test it +import * as vscode from 'vscode'; +// import * as myExtension from '../../extension'; + +suite('Extension Test Suite', () => { + vscode.window.showInformationMessage('Start all tests.'); + + test('Sample test', () => { + assert.strictEqual(-1, [1, 2, 3].indexOf(5)); + assert.strictEqual(-1, [1, 2, 3].indexOf(0)); + }); +}); diff --git a/caesar-ext/tsconfig.json b/caesar-ext/tsconfig.json new file mode 100644 index 0000000..6954702 --- /dev/null +++ b/caesar-ext/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "Node16", + "target": "ES2022", + "outDir": "out", + "lib": [ + "ES2022" + ], + "sourceMap": true, + "rootDir": "src", + "strict": true /* enable all strict type-checking options */ + /* Additional Checks */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + } +} diff --git a/caesar-ext/vsc-extension-quickstart.md b/caesar-ext/vsc-extension-quickstart.md new file mode 100644 index 0000000..3d8ce06 --- /dev/null +++ b/caesar-ext/vsc-extension-quickstart.md @@ -0,0 +1,43 @@ +# Welcome to your VS Code Extension + +## What's in the folder + +* This folder contains all of the files necessary for your extension. +* `package.json` - this is the manifest file in which you declare your extension and command. + * The sample plugin registers a command and defines its title and command name. With this information VS Code can show the command in the command palette. It doesn’t yet need to load the plugin. +* `src/extension.ts` - this is the main file where you will provide the implementation of your command. + * The file exports one function, `activate`, which is called the very first time your extension is activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`. + * We pass the function containing the implementation of the command as the second parameter to `registerCommand`. + +## Get up and running straight away + +* Press `F5` to open a new window with your extension loaded. +* Run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`. +* Set breakpoints in your code inside `src/extension.ts` to debug your extension. +* Find output from your extension in the debug console. + +## Make changes + +* You can relaunch the extension from the debug toolbar after changing code in `src/extension.ts`. +* You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes. + +## Explore the API + +* You can open the full set of our API when you open the file `node_modules/@types/vscode/index.d.ts`. + +## Run tests + +* Install the [Extension Test Runner](https://marketplace.visualstudio.com/items?itemName=ms-vscode.extension-test-runner) +* Run the "watch" task via the **Tasks: Run Task** command. Make sure this is running, or tests might not be discovered. +* Open the Testing view from the activity bar and click the Run Test" button, or use the hotkey `Ctrl/Cmd + ; A` +* See the output of the test result in the Test Results view. +* Make changes to `src/test/extension.test.ts` or create new test files inside the `test` folder. + * The provided test runner will only consider files matching the name pattern `**.test.ts`. + * You can create folders inside the `test` folder to structure your tests any way you want. + +## Go further + +* [Follow UX guidelines](https://code.visualstudio.com/api/ux-guidelines/overview) to create extensions that seamlessly integrate with VS Code's native interface and patterns. + * Reduce the extension size and improve the startup time by [bundling your extension](https://code.visualstudio.com/api/working-with-extensions/bundling-extension). + * [Publish your extension](https://code.visualstudio.com/api/working-with-extensions/publishing-extension) on the VS Code extension marketplace. + * Automate builds by setting up [Continuous Integration](https://code.visualstudio.com/api/working-with-extensions/continuous-integration). diff --git a/src/driver.rs b/src/driver.rs index 24f862a..2caed01 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -2,31 +2,50 @@ use std::{ fmt, + fs::{create_dir_all, File}, + io::{self, Write}, ops::{Deref, DerefMut}, }; use crate::{ ast::{ - visit::VisitorMut, Block, DeclKind, Expr, ExprData, ExprKind, LitKind, Shared, - SourceFilePath, Span, Spanned, StoredFile, TyKind, + stats::StatsVisitor, visit::VisitorMut, BinOpKind, Block, DeclKind, Expr, ExprData, + ExprKind, LitKind, Shared, SourceFilePath, Span, Spanned, StoredFile, TyKind, }, - front::parser, - front::resolve::{Resolve, ResolveError}, front::{ - parser::ParseError, + parser::{self, ParseError}, + resolve::{Resolve, ResolveError}, tycheck::{Tycheck, TycheckError}, }, intrinsic::annotations::AnnotationError, + opt::{ + boolify::Boolify, egraph, qelim::Qelim, relational::Relational, unfolder::Unfolder, + RemoveParens, + }, pretty::{Doc, SimplePretty}, procs::{ monotonicity::{MonotonicityError, MonotonicityVisitor}, verify_proc, SpecCall, }, proof_rules::EncCall, + smt::{translate_exprs::TranslateExprs, SmtCtx}, tyctx::TyCtx, - vc::vcgen::Vcgen, + vc::{subst::apply_subst, vcgen::Vcgen}, + version::write_detailed_version_info, + Options, VerifyError, +}; + +use z3::{ + ast::{Ast, Bool}, + Config, Context, }; -use tracing::{info_span, instrument, trace}; +use z3rro::{ + pretty::{get_pretty_solver_smtlib, get_solver_smtlib}, + prover::{ProveResult, Prover}, + util::{PrefixWriter, ReasonUnknown}, +}; + +use tracing::{info, info_span, instrument, trace}; /// Human-readable name for a source unit. Used for debugging and error messages. #[derive(Debug)] @@ -335,6 +354,103 @@ impl VerifyUnit { }); Ok(vcgen.vcgen_stmts(&self.0, infinity)) } + + pub fn verify( + &mut self, + name: &SourceUnitName, + mut tcx: &mut TyCtx, + options: &Options, + ) -> Result { + // 4. Desugaring: transforming spec calls to procs + self.desugar(&mut tcx).unwrap(); + + // print HeyVL core after desugaring if requested + if options.print_core { + println!("{}: HeyVL core query:\n{}\n", name, *self); + } + + // 5. Generating verification conditions + let vcgen = Vcgen::new(&tcx, options.print_label_vc); + let mut vc_expr = self.vcgen(&vcgen).unwrap(); + + // 6. Unfolding + unfold_expr(options, &tcx, &mut vc_expr); + + // 7. Quantifier elimination + if !options.no_qelim { + apply_qelim(&mut tcx, &mut vc_expr); + } + + // In-between, gather some stats about the vc expression + trace_expr_stats(&mut vc_expr); + + // 8. Create the "vc[S] is valid" expression + let mut vc_expr_eq_infinity = expr_eq_infty(vc_expr); + + if options.egraph { + egraph::simplify(&vc_expr_eq_infinity); + } + + // 9. Optimizations + if !options.no_boolify || options.opt_rel { + RemoveParens.visit_expr(&mut vc_expr_eq_infinity).unwrap(); + } + if !options.no_boolify { + apply_boolify_opt(&mut vc_expr_eq_infinity); + } + if options.opt_rel { + apply_relational_opt(&mut vc_expr_eq_infinity); + } + + // print theorem to prove if requested + if options.print_theorem { + println!("{}: Theorem to prove:\n{}\n", name, &vc_expr_eq_infinity); + } + + // 10. Translate to Z3 + let translate_span = info_span!("translation to Z3"); + let translate_entered = translate_span.enter(); + + let ctx = mk_z3_ctx(options); + let smt_ctx = SmtCtx::new(&ctx, &tcx); + let mut smt_translate = TranslateExprs::new(&smt_ctx); + let mut valid_query = smt_translate.t_bool(&vc_expr_eq_infinity); + + drop(translate_entered); + drop(translate_span); + + if !options.no_simplify { + info_span!("simplify query").in_scope(|| valid_query = valid_query.simplify()); + } + + // 11. Create Z3 solver with axioms, solve + let sat_span = info_span!("SAT check"); + let sat_entered = sat_span.enter(); + + let mut prover = mk_valid_query_prover(&ctx, &smt_translate, &valid_query); + let smtlib = get_smtlib(options, &prover); + + let result = prover.check_proof(); + + drop(sat_entered); + drop(sat_span); + + // Now let's examine the result. + print_prove_result(result, name, &prover); + + write_smtlib(options, smtlib, name, result).unwrap(); + + if options.z3_trace { + info!("Z3 tracing output will be written to `z3.log`."); + } + + // If the solver was interrupted from the keyboard, exit now. + if prover.get_reason_unknown() == Some(ReasonUnknown::Interrupted) { + return Err(VerifyError::Interrupted); + } + + Ok(result == ProveResult::Proof) + } } impl SimplePretty for VerifyUnit { @@ -348,3 +464,157 @@ impl fmt::Display for VerifyUnit { self.pretty().render_fmt(80, f) } } + +fn apply_qelim(tcx: &mut TyCtx, vc_expr: &mut Expr) { + let mut qelim = Qelim::new(tcx); + qelim.qelim_inf(vc_expr); + // Apply/eliminate substitutions again + apply_subst(tcx, vc_expr); +} + +fn apply_relational_opt(vc_expr_eq_infinity: &mut Expr) { + let span = info_span!("relationalize"); + let _entered = span.enter(); + (Relational {}).visit_expr(vc_expr_eq_infinity).unwrap(); +} + +fn apply_boolify_opt(vc_expr_eq_infinity: &mut Expr) { + let span = info_span!("boolify"); + let _entered = span.enter(); + (Boolify {}).visit_expr(vc_expr_eq_infinity).unwrap(); +} + +fn unfold_expr(options: &Options, tcx: &TyCtx, vc_expr: &mut Expr) { + let span = info_span!("unfolding"); + let _entered = span.enter(); + if !options.strict { + let ctx = Context::new(&Config::default()); + let smt_ctx = SmtCtx::new(&ctx, tcx); + let mut unfolder = Unfolder::new(&smt_ctx); + unfolder.visit_expr(vc_expr).unwrap(); + } else { + apply_subst(tcx, vc_expr); + } +} + +fn mk_z3_ctx(options: &Options) -> Context { + let mut config = Config::default(); + if options.z3_trace { + config.set_bool_param_value("trace", true); + config.set_bool_param_value("proof", true); + } + Context::new(&config) +} + +fn mk_valid_query_prover<'smt, 'ctx>( + ctx: &'ctx Context, + smt_translate: &TranslateExprs<'smt, 'ctx>, + valid_query: &Bool<'ctx>, +) -> Prover<'ctx> { + // create the prover and set the params + let mut prover = Prover::new(ctx); + // add assumptions (from axioms and locals) to the prover + smt_translate + .ctx + .uninterpreteds() + .add_axioms_to_prover(&mut prover); + smt_translate + .local_scope() + .add_assumptions_to_prover(&mut prover); + // add the provable: is this Boolean true? + prover.add_provable(valid_query); + prover +} + +fn trace_expr_stats(vc_expr: &mut Expr) { + let mut stats = StatsVisitor::default(); + stats.visit_expr(vc_expr).unwrap(); + let stats = stats.stats; + tracing::info!( + num_exprs = stats.num_exprs, + num_quants = stats.num_quants, + depths = %stats.depths_summary(), + "Verification condition stats" + ); + if stats.num_quants > 0 { + tracing::warn!( + num_quants=stats.num_quants, "Quantifiers are present in the generated verification conditions. It is possible that quantifier elimination failed. If Z3 can't decide the problem, this may be the reason." + ); + } +} + +fn expr_eq_infty(vc_expr: Expr) -> Expr { + let infinity = Shared::new(ExprData { + kind: ExprKind::Lit(Spanned::with_dummy_span(LitKind::Infinity)), + ty: Some(TyKind::EUReal), + span: Span::dummy_span(), + }); + Shared::new(ExprData { + kind: ExprKind::Binary(Spanned::with_dummy_span(BinOpKind::Eq), infinity, vc_expr), + ty: Some(TyKind::Bool), + span: Span::dummy_span(), + }) +} + +fn print_prove_result(result: ProveResult, name: &SourceUnitName, prover: &Prover) { + match result { + ProveResult::Proof => println!("{}: Verified.", name), + ProveResult::Counterexample => { + println!("{}: Counter-example to verification found!", name); + if let Some(model) = prover.get_model() { + println!("{:?}", model); + }; + } + ProveResult::Unknown => { + if let Some(reason) = prover.get_reason_unknown() { + println!("{}: Unknown result! (reason: {})", name, reason) + } else { + println!("{}: Unknown result!", name) + } + } + } +} + +fn get_smtlib(options: &Options, prover: &Prover) -> Option { + if options.print_smt || options.smt_dir.is_some() { + let smtlib = if !options.no_pretty_smtlib { + get_pretty_solver_smtlib(prover.solver()) + } else { + get_solver_smtlib(prover.solver()) + }; + Some(smtlib) + } else { + None + } +} + +fn write_smtlib( + options: &Options, + smtlib: Option, + name: &SourceUnitName, + result: ProveResult, +) -> io::Result<()> { + if options.print_smt || options.smt_dir.is_some() { + let mut smtlib = smtlib.unwrap(); + if result == ProveResult::Counterexample { + smtlib.push_str("\n(get-model)\n"); + } else if result == ProveResult::Unknown { + smtlib.push_str("\n(get-info :reason-unknown)\n"); + } + if options.print_smt { + println!("\n; --- Solver SMT-LIB ---\n{}\n", smtlib); + } + if let Some(smt_dir) = &options.smt_dir { + let file_path = smt_dir.join(format!("{}.smt2", name)); + create_dir_all(file_path.parent().unwrap())?; + let mut file = File::create(&file_path)?; + let mut comment_writer = PrefixWriter::new("; ".as_bytes(), &mut file); + write_detailed_version_info(&mut comment_writer)?; + writeln!(comment_writer, "Source unit: {}", name)?; + writeln!(comment_writer, "Prove result: {:?}", result)?; + file.write_all(smtlib.as_bytes())?; + info!(?file_path, "SMT-LIB query written to file"); + } + } + Ok(()) +} diff --git a/src/language_server/language_server_main.rs b/src/language_server/language_server_main.rs new file mode 100644 index 0000000..dc60054 --- /dev/null +++ b/src/language_server/language_server_main.rs @@ -0,0 +1,161 @@ +use lsp_server::{Connection, Message, Request, RequestId, Response}; +use lsp_types::{ + lsp_notification, Diagnostic, DiagnosticSeverity, DidSaveTextDocumentParams, TextDocumentItem, + Url, +}; +use lsp_types::{ + notification::Notification, DidChangeTextDocumentParams, DidChangeWorkspaceFoldersParams, + DidCloseTextDocumentParams, DidOpenTextDocumentParams, ServerCapabilities, + TextDocumentSyncCapability, TextDocumentSyncKind, WorkspaceFolder, +}; +use serde_json::json; +use std::error::Error; +use std::io::{self, BufRead, BufReader, Write}; +use std::process::{Command, Stdio}; +use std::sync::Arc; +use std::sync::Mutex; + +use crate::procs::verify_proc; +use crate::{get_verify_units_from_files, VerifyError}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +struct VerificationStatusParams { + text_document: TextDocumentItem, +} + +impl lsp_types::request::Request for VerificationStatusParams { + type Params = VerificationStatusParams; + type Result = bool; + const METHOD: &'static str = "custom/verifyStatus"; +} + +fn main() -> Result<(), Box> { + let (connection, io_threads) = Connection::stdio(); + let server_capabilities = ServerCapabilities { + text_document_sync: Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::NONE)), + ..ServerCapabilities::default() + }; + + connection.initialize(serde_json::json!(server_capabilities))?; + + let mut documents = Arc::new(Mutex::new(Vec::new())); + let mut workspace_folders = Arc::new(Mutex::new(Vec::new())); + // let mut verify_units = Vec::new(); + + for msg in &connection.receiver { + match msg { + Message::Request(req) => { + handle_request(req, &connection, &mut documents, &mut workspace_folders)?; + } + Message::Notification(not) => { + handle_notification(not, &connection, &mut documents, &mut workspace_folders)?; + } + _ => (), + } + } + + Ok(()) +} + +fn handle_request( + req: Request, + connection: &Connection, + documents: &mut Arc>>, + workspace_folders: &mut Arc>>, +) -> Result<(), Box> { + match req.method.as_str() { + // "custom/procStatus" => { + // let params = serde_json::from_value(req.params)?; + // let text = params.text_document.text; + // } + _ => { + let response = Response::new_err( + req.id, + lsp_server::ErrorCode::MethodNotFound as i32, + "Method not found".to_string(), + ); + connection.sender.send(Message::Response(response))?; + } + } + Ok(()) +} + +fn handle_notification( + not: lsp_server::Notification, + connection: &Connection, + documents: &mut Arc>>, + workspace_folders: &mut Arc>>, +) -> Result<(), Box> { + match not.method.as_str() { + "textDocument/didOpen" => { + // let params: DidOpenTextDocumentParams = serde_json::from_value(not.params.clone())?; + // let uri = params.text_document.uri; + // let text = params.text_document.text; + // documents.lock().unwrap().push((uri.to_string(), text)); + + // let handle_error = |result: Result<_, VerifyError>| match result { + // Ok(value) => Ok(value), + // Err(e) => { + // // Handle VerifyError + // // ... + // Err(e) + // } + // }; + + // let (mut verify_units, mut tcx) = + // get_verify_units_from_files(options, files_mutex, user_files); + + // let mut all_proven: bool = true; + // for verify_unit in &mut verify_units { + // let (name, mut verify_unit) = verify_unit.enter_with_name(); + + // let result = verify_unit.verify(name, &mut tcx, options)?; + + // all_proven = all_proven && result; + // } + + // match get_verify_units_from_files(options, files_mutex, user_files) { + // Ok((verify_units, tcx)) => {} + // Err(e) => match e { + // VerifyError::Diagnostic(diagnostic) => {} + // VerifyError::IoError(err) => {} + // VerifyError::LimitError(_) => {} + // VerifyError::Panic(_) => {} + // }, + // } + } + "textDocument/didSave" => { + let params: DidSaveTextDocumentParams = serde_json::from_value(not.params.clone())?; + let uri = params.text_document.uri; + let text = params.text.unwrap(); + documents.lock().unwrap().push((uri.to_string(), text)); + } + "textDocument/didChange" => { + let params: DidChangeTextDocumentParams = serde_json::from_value(not.params.clone())?; + let uri = params.text_document.uri; + let content_changes = params.content_changes; + let mut documents = documents.lock().unwrap(); + } + "textDocument/didClose" => { + let params: DidCloseTextDocumentParams = serde_json::from_value(not.params.clone())?; + let uri = params.text_document.uri; + documents + .lock() + .unwrap() + .retain(|(doc_uri, _)| !matches!(doc_uri.clone(), uri)); + } + "workspace/didChangeWorkspaceFolders" => { + let params: DidChangeWorkspaceFoldersParams = + serde_json::from_value(not.params.clone())?; + let event = params.event; + let mut workspace_folders = workspace_folders.lock().unwrap(); + workspace_folders.extend(event.added.clone()); + workspace_folders.retain(|folder| !event.removed.contains(folder)); + } + _ => (), + } + Ok(()) +} + +fn verify_and_store() {} diff --git a/src/language_server/mod.rs b/src/language_server/mod.rs new file mode 100644 index 0000000..cb6ffa8 --- /dev/null +++ b/src/language_server/mod.rs @@ -0,0 +1 @@ +pub mod language_server_main; diff --git a/src/main.rs b/src/main.rs index 865c8b9..a7cdf16 100644 --- a/src/main.rs +++ b/src/main.rs @@ -52,6 +52,7 @@ pub mod ast; mod driver; pub mod front; pub mod intrinsic; +mod language_server; pub mod opt; pub mod pretty; mod procs; @@ -361,6 +362,26 @@ fn verify_files_main( files_mutex: &Mutex, user_files: &[FileId], ) -> Result { + let (mut verify_units, mut tcx) = + get_verify_units_from_files(options, files_mutex, user_files)?; + + let mut all_proven: bool = true; + for verify_unit in &mut verify_units { + let (name, mut verify_unit) = verify_unit.enter_with_name(); + + let result = verify_unit.verify(name, &mut tcx, options)?; + + all_proven = all_proven && result; + } + + Ok(all_proven) +} + +pub fn get_verify_units_from_files( + options: &Options, + files_mutex: &Mutex, + user_files: &[FileId], +) -> Result<(Vec>, TyCtx), VerifyError> { // 1. Parsing let mut source_units: Vec> = Vec::new(); let mut files = files_mutex.lock().unwrap(); @@ -448,102 +469,7 @@ fn verify_files_main( warn!("Z3 tracing is enabled with multiple verification units. Intermediate tracing results will be overwritten."); } - let mut all_proven: bool = true; - for verify_unit in &mut verify_units { - let (name, mut verify_unit) = verify_unit.enter_with_name(); - - // 4. Desugaring: transforming spec calls to procs - verify_unit.desugar(&mut tcx).unwrap(); - - // print HeyVL core after desugaring if requested - if options.print_core { - println!("{}: HeyVL core query:\n{}\n", name, *verify_unit); - } - - // 5. Generating verification conditions - let vcgen = Vcgen::new(&tcx, options.print_label_vc); - let mut vc_expr = verify_unit.vcgen(&vcgen).unwrap(); - - // 6. Unfolding - unfold_expr(options, &tcx, &mut vc_expr); - - // 7. Quantifier elimination - if !options.no_qelim { - apply_qelim(&mut tcx, &mut vc_expr); - } - - // In-between, gather some stats about the vc expression - trace_expr_stats(&mut vc_expr); - - // 8. Create the "vc[S] is valid" expression - let mut vc_expr_eq_infinity = expr_eq_infty(vc_expr); - - if options.egraph { - egraph::simplify(&vc_expr_eq_infinity); - } - - // 9. Optimizations - if !options.no_boolify || options.opt_rel { - RemoveParens.visit_expr(&mut vc_expr_eq_infinity).unwrap(); - } - if !options.no_boolify { - apply_boolify_opt(&mut vc_expr_eq_infinity); - } - if options.opt_rel { - apply_relational_opt(&mut vc_expr_eq_infinity); - } - - // print theorem to prove if requested - if options.print_theorem { - println!("{}: Theorem to prove:\n{}\n", name, &vc_expr_eq_infinity); - } - - // 10. Translate to Z3 - let translate_span = info_span!("translation to Z3"); - let translate_entered = translate_span.enter(); - - let ctx = mk_z3_ctx(options); - let smt_ctx = SmtCtx::new(&ctx, &tcx); - let mut smt_translate = TranslateExprs::new(&smt_ctx); - let mut valid_query = smt_translate.t_bool(&vc_expr_eq_infinity); - - drop(translate_entered); - drop(translate_span); - - if !options.no_simplify { - info_span!("simplify query").in_scope(|| valid_query = valid_query.simplify()); - } - - // 11. Create Z3 solver with axioms, solve - let sat_span = info_span!("SAT check"); - let sat_entered = sat_span.enter(); - - let mut prover = mk_valid_query_prover(&ctx, &smt_translate, &valid_query); - let smtlib = get_smtlib(options, &prover); - - let result = prover.check_proof(); - - drop(sat_entered); - drop(sat_span); - - // Now let's examine the result. - print_prove_result(result, name, &prover); - - write_smtlib(options, smtlib, name, result).unwrap(); - - if options.z3_trace { - info!("Z3 tracing output will be written to `z3.log`."); - } - - // If the solver was interrupted from the keyboard, exit now. - if prover.get_reason_unknown() == Some(ReasonUnknown::Interrupted) { - return Err(VerifyError::Interrupted); - } - - all_proven = all_proven && result == ProveResult::Proof; - } - - Ok(all_proven) + Ok((verify_units, tcx)) } fn setup_tracing(options: &Options) { diff --git a/vscode-ext/package-lock.json b/vscode-ext/package-lock.json new file mode 100644 index 0000000..6ad640b --- /dev/null +++ b/vscode-ext/package-lock.json @@ -0,0 +1,470 @@ +{ + "name": "heyvl", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "heyvl", + "version": "0.0.1", + "devDependencies": { + "@types/node": "^8.10.25", + "@types/vscode": "^1.71.0", + "tslint": "^5.16.0", + "typescript": "^3.4.5" + }, + "engines": { + "vscode": "^1.71.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@types/node": { + "version": "8.10.66", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", + "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==", + "dev": true + }, + "node_modules/@types/vscode": { + "version": "1.87.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.87.0.tgz", + "integrity": "sha512-y3yYJV2esWr8LNjp3VNbSMWG7Y43jC8pCldG8YwiHGAQbsymkkMMt0aDT1xZIOFM2eFcNiUc+dJMx1+Z0UT8fg==", + "dev": true + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/hasown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tslint": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", + "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.29.0" + }, + "bin": { + "tslint": "bin/tslint" + }, + "engines": { + "node": ">=4.8.0" + }, + "peerDependencies": { + "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev" + } + }, + "node_modules/tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "peerDependencies": { + "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" + } + }, + "node_modules/typescript": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", + "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + } + } +} diff --git a/vscode-ext/package.json b/vscode-ext/package.json index fbbcbdd..ea6ec43 100644 --- a/vscode-ext/package.json +++ b/vscode-ext/package.json @@ -9,17 +9,45 @@ "categories": [ "Programming Languages" ], + "activationEvents": [], + "main": "./out/extension.js", "contributes": { - "languages": [{ - "id": "heyvl", - "aliases": ["HeyVL", "heyvl"], - "extensions": [".heyvl"], - "configuration": "./language-configuration.json" - }], - "grammars": [{ - "language": "heyvl", - "scopeName": "source.heyvl", - "path": "./syntaxes/heyvl.tmLanguage.json" - }] + "commands": [ + { + "command": "helloworld.helloWorld", + "title": "Hello World" + } + ], + "languages": [ + { + "id": "heyvl", + "aliases": [ + "HeyVL", + "heyvl" + ], + "extensions": [ + ".heyvl" + ], + "configuration": "./language-configuration.json" + } + ], + "grammars": [ + { + "language": "heyvl", + "scopeName": "source.heyvl", + "path": "./syntaxes/heyvl.tmLanguage.json" + } + ] + }, + "scripts": { + "vscode:prepublish": "npm run compile", + "compile": "tsc -p ./", + "watch": "tsc -watch -p ./" + }, + "devDependencies": { + "@types/node": "^8.10.25", + "@types/vscode": "^1.71.0", + "tslint": "^5.16.0", + "typescript": "^3.4.5" } } diff --git a/vscode-ext/src/extension.ts b/vscode-ext/src/extension.ts new file mode 100644 index 0000000..f2121b9 --- /dev/null +++ b/vscode-ext/src/extension.ts @@ -0,0 +1,26 @@ +// The module 'vscode' contains the VS Code extensibility API +// Import the module and reference it with the alias vscode in your code below +import * as vscode from 'vscode'; + +// this method is called when your extension is activated +// your extension is activated the very first time the command is executed +export function activate(context: vscode.ExtensionContext) { + // Use the console to output diagnostic information (console.log) and errors (console.error) + // This line of code will only be executed once when your extension is activated + console.log('Congratulations, your extension "helloworld-sample" is now active!'); + + // The command has been defined in the package.json file + // Now provide the implementation of the command with registerCommand + // The commandId parameter must match the command field in package.json + let disposable = vscode.commands.registerCommand('helloworld.helloWorld', () => { + // The code you place here will be executed every time your command is executed + + // Display a message box to the user + vscode.window.showInformationMessage('Hello World!'); + }); + + context.subscriptions.push(disposable); +} + +// this method is called when your extension is deactivated +export function deactivate() { } From 0999923dea3249a69ff60c275367848cc4310094 Mon Sep 17 00:00:00 2001 From: umutdural Date: Wed, 27 Mar 2024 12:56:45 +0100 Subject: [PATCH 02/25] language server: checkmark backend initial functionality --- src/ast/diagnostic.rs | 66 ++++++ src/driver.rs | 14 +- src/front/tycheck.rs | 2 +- src/language_server/language_server_main.rs | 217 +++++++++++++------- src/main.rs | 204 ++---------------- src/procs/spec_call.rs | 2 +- 6 files changed, 242 insertions(+), 263 deletions(-) diff --git a/src/ast/diagnostic.rs b/src/ast/diagnostic.rs index a43bac5..3d8f165 100644 --- a/src/ast/diagnostic.rs +++ b/src/ast/diagnostic.rs @@ -198,6 +198,43 @@ impl Span { variant, } } + + pub fn to_lsp_range(self, files: &Files) -> Option { + let file = files.get(file_id).unwrap(); + let char_span = file.char_span(self); + + let mut start_line = 0; + let mut start_offset = 0; + let mut end_line = 0; + let mut end_offset = 0; + + for (i, c) in file.source.chars().enumerate() { + if i == char_span.end { + break; + } + if i == char_span.start { + (start_line, start_offset) = (end_line, end_offset); + } + + if c == '\n' { + end_line += 1; + end_offset = 0; + } else { + end_offset += 1; + } + } + + Some(lsp_types::Range { + start: lsp_types::Position { + line: start_line, + character: start_offset, + }, + end: lsp_types::Position { + line: end_line, + character: end_offset, + }, + }) + } } // TODO: this debug impl isn't great @@ -367,6 +404,35 @@ impl Diagnostic { builder } + pub fn into_lsp_diagnostic(self, files: &Files) -> lsp_types::Diagnostic { + let span = self.0.location; + let range = span.to_lsp_range(files).unwrap(); + let severity = match self.0.kind { + ReportKind::Error => lsp_types::DiagnosticSeverity::ERROR, + ReportKind::Warning => lsp_types::DiagnosticSeverity::WARNING, + ReportKind::Advice => lsp_types::DiagnosticSeverity::HINT, + _ => lsp_types::DiagnosticSeverity::ERROR, + }; + let code = self + .0 + .code + .map(|code| lsp_types::NumberOrString::Number(code as i32)); + let code_description = None; + let source = None; + let message = self.0.msg.unwrap_or_else(|| "(no message)".to_string()); + lsp_types::Diagnostic { + range, + severity: Some(severity), + code, + code_description, + source, + message, + related_information: None, + tags: None, + data: None, + } + } + /// Write the diagnostic to a simple [`String`] without ANSI colors. /// /// This is useful for testing. diff --git a/src/driver.rs b/src/driver.rs index 2caed01..a2980b5 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -48,7 +48,7 @@ use z3rro::{ use tracing::{info, info_span, instrument, trace}; /// Human-readable name for a source unit. Used for debugging and error messages. -#[derive(Debug)] +#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone)] pub struct SourceUnitName(String); impl SourceUnitName { @@ -358,11 +358,11 @@ impl VerifyUnit { pub fn verify( &mut self, name: &SourceUnitName, - mut tcx: &mut TyCtx, + tcx: &mut TyCtx, options: &Options, ) -> Result { // 4. Desugaring: transforming spec calls to procs - self.desugar(&mut tcx).unwrap(); + self.desugar(tcx).unwrap(); // print HeyVL core after desugaring if requested if options.print_core { @@ -370,15 +370,15 @@ impl VerifyUnit { } // 5. Generating verification conditions - let vcgen = Vcgen::new(&tcx, options.print_label_vc); + let vcgen = Vcgen::new(tcx, options.print_label_vc); let mut vc_expr = self.vcgen(&vcgen).unwrap(); // 6. Unfolding - unfold_expr(options, &tcx, &mut vc_expr); + unfold_expr(options, tcx, &mut vc_expr); // 7. Quantifier elimination if !options.no_qelim { - apply_qelim(&mut tcx, &mut vc_expr); + apply_qelim(tcx, &mut vc_expr); } // In-between, gather some stats about the vc expression @@ -412,7 +412,7 @@ impl VerifyUnit { let translate_entered = translate_span.enter(); let ctx = mk_z3_ctx(options); - let smt_ctx = SmtCtx::new(&ctx, &tcx); + let smt_ctx = SmtCtx::new(&ctx, tcx); let mut smt_translate = TranslateExprs::new(&smt_ctx); let mut valid_query = smt_translate.t_bool(&vc_expr_eq_infinity); diff --git a/src/front/tycheck.rs b/src/front/tycheck.rs index 5e5b582..ecb4fb6 100644 --- a/src/front/tycheck.rs +++ b/src/front/tycheck.rs @@ -853,6 +853,6 @@ mod test { test() } "#; - parse_decls_and_tycheck(&source).unwrap(); + parse_decls_and_tycheck(source).unwrap(); } } diff --git a/src/language_server/language_server_main.rs b/src/language_server/language_server_main.rs index dc60054..56ffe72 100644 --- a/src/language_server/language_server_main.rs +++ b/src/language_server/language_server_main.rs @@ -1,22 +1,23 @@ -use lsp_server::{Connection, Message, Request, RequestId, Response}; +use lsp_server::{Connection, Message, Request, Response}; use lsp_types::{ - lsp_notification, Diagnostic, DiagnosticSeverity, DidSaveTextDocumentParams, TextDocumentItem, - Url, + DidChangeTextDocumentParams, DidChangeWorkspaceFoldersParams, DidCloseTextDocumentParams, + DidOpenTextDocumentParams, ServerCapabilities, TextDocumentSyncCapability, + TextDocumentSyncKind, WorkspaceFolder, }; -use lsp_types::{ - notification::Notification, DidChangeTextDocumentParams, DidChangeWorkspaceFoldersParams, - DidCloseTextDocumentParams, DidOpenTextDocumentParams, ServerCapabilities, - TextDocumentSyncCapability, TextDocumentSyncKind, WorkspaceFolder, -}; -use serde_json::json; +use lsp_types::{DidSaveTextDocumentParams, TextDocumentItem, Url}; + +use std::collections::HashMap; use std::error::Error; -use std::io::{self, BufRead, BufReader, Write}; -use std::process::{Command, Stdio}; + use std::sync::Arc; use std::sync::Mutex; -use crate::procs::verify_proc; -use crate::{get_verify_units_from_files, VerifyError}; +use crate::ast::decl::DeclKind; +use crate::ast::{Files, Span, StoredFile}; +use crate::driver::{SourceUnit, SourceUnitName}; +use crate::{ + get_source_units_from_files, load_file, transform_source_to_verify, Options, VerifyError, +}; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] @@ -31,7 +32,7 @@ impl lsp_types::request::Request for VerificationStatusParams { } fn main() -> Result<(), Box> { - let (connection, io_threads) = Connection::stdio(); + let (connection, _) = Connection::stdio(); let server_capabilities = ServerCapabilities { text_document_sync: Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::NONE)), ..ServerCapabilities::default() @@ -41,15 +42,27 @@ fn main() -> Result<(), Box> { let mut documents = Arc::new(Mutex::new(Vec::new())); let mut workspace_folders = Arc::new(Mutex::new(Vec::new())); - // let mut verify_units = Vec::new(); + let mut proc_status_map: HashMap> = HashMap::new(); for msg in &connection.receiver { match msg { Message::Request(req) => { - handle_request(req, &connection, &mut documents, &mut workspace_folders)?; + handle_request( + req, + &connection, + &mut documents, + &mut workspace_folders, + &mut proc_status_map, + )?; } Message::Notification(not) => { - handle_notification(not, &connection, &mut documents, &mut workspace_folders)?; + handle_notification( + not, + &connection, + &mut documents, + &mut workspace_folders, + &mut proc_status_map, + )?; } _ => (), } @@ -61,23 +74,27 @@ fn main() -> Result<(), Box> { fn handle_request( req: Request, connection: &Connection, - documents: &mut Arc>>, - workspace_folders: &mut Arc>>, + _documents: &mut Arc>>, + _workspace_folders: &mut Arc>>, + proc_status_map: &mut HashMap>, ) -> Result<(), Box> { - match req.method.as_str() { - // "custom/procStatus" => { - // let params = serde_json::from_value(req.params)?; - // let text = params.text_document.text; - // } - _ => { - let response = Response::new_err( - req.id, - lsp_server::ErrorCode::MethodNotFound as i32, - "Method not found".to_string(), - ); - connection.sender.send(Message::Response(response))?; + let response: Response = match req.method.as_str() { + "custom/procStatus" => { + let params: VerificationStatusParams = serde_json::from_value(req.params)?; + let uri = params.text_document.uri; + + let status_vec = proc_status_map.get(&uri).unwrap(); + + let proc_status_json = serde_json::to_value(status_vec)?; + Response::new_ok(req.id, proc_status_json) } - } + _ => Response::new_err( + req.id, + lsp_server::ErrorCode::MethodNotFound as i32, + "Method not found".to_string(), + ), + }; + connection.sender.send(Message::Response(response))?; Ok(()) } @@ -86,44 +103,16 @@ fn handle_notification( connection: &Connection, documents: &mut Arc>>, workspace_folders: &mut Arc>>, + proc_status_map: &mut HashMap>, ) -> Result<(), Box> { match not.method.as_str() { "textDocument/didOpen" => { - // let params: DidOpenTextDocumentParams = serde_json::from_value(not.params.clone())?; - // let uri = params.text_document.uri; - // let text = params.text_document.text; - // documents.lock().unwrap().push((uri.to_string(), text)); - - // let handle_error = |result: Result<_, VerifyError>| match result { - // Ok(value) => Ok(value), - // Err(e) => { - // // Handle VerifyError - // // ... - // Err(e) - // } - // }; - - // let (mut verify_units, mut tcx) = - // get_verify_units_from_files(options, files_mutex, user_files); - - // let mut all_proven: bool = true; - // for verify_unit in &mut verify_units { - // let (name, mut verify_unit) = verify_unit.enter_with_name(); - - // let result = verify_unit.verify(name, &mut tcx, options)?; - - // all_proven = all_proven && result; - // } - - // match get_verify_units_from_files(options, files_mutex, user_files) { - // Ok((verify_units, tcx)) => {} - // Err(e) => match e { - // VerifyError::Diagnostic(diagnostic) => {} - // VerifyError::IoError(err) => {} - // VerifyError::LimitError(_) => {} - // VerifyError::Panic(_) => {} - // }, - // } + let params: DidOpenTextDocumentParams = serde_json::from_value(not.params.clone())?; + let uri = params.text_document.uri; + let text = params.text_document.text; + documents.lock().unwrap().push((uri.to_string(), text)); + + verify_and_cache(uri, connection, proc_status_map) } "textDocument/didSave" => { let params: DidSaveTextDocumentParams = serde_json::from_value(not.params.clone())?; @@ -134,8 +123,10 @@ fn handle_notification( "textDocument/didChange" => { let params: DidChangeTextDocumentParams = serde_json::from_value(not.params.clone())?; let uri = params.text_document.uri; - let content_changes = params.content_changes; - let mut documents = documents.lock().unwrap(); + // let _content_changes = params.content_changes; + // let mut _documents = documents.lock().unwrap(); + + verify_and_cache(uri, connection, proc_status_map); } "textDocument/didClose" => { let params: DidCloseTextDocumentParams = serde_json::from_value(not.params.clone())?; @@ -144,6 +135,8 @@ fn handle_notification( .lock() .unwrap() .retain(|(doc_uri, _)| !matches!(doc_uri.clone(), uri)); + + proc_status_map.remove(&uri); } "workspace/didChangeWorkspaceFolders" => { let params: DidChangeWorkspaceFoldersParams = @@ -158,4 +151,88 @@ fn handle_notification( Ok(()) } -fn verify_and_store() {} +fn push_diagnostics( + connection: &Connection, + uri: Url, + diagnostics: Vec, +) -> Result<(), Box> { + let params = lsp_types::PublishDiagnosticsParams { + uri, + diagnostics, + version: None, + }; + let not = lsp_server::Notification::new("textDocument/publishDiagnostics".to_string(), params); + connection + .sender + .send(lsp_server::Message::Notification(not))?; + Ok(()) +} + +fn verify_and_cache( + uri: Url, + connection: &Connection, + proc_status_map: &mut HashMap>, +) { + let proc_status = proc_status_map.entry(uri.clone()).or_default(); + + let path = uri + .to_file_path() + .expect("Failed to convert URI to file path"); + + let mut files = Files::new(); + let file_id = load_file(&mut files, &path); + + let files_mutex = Mutex::new(files); + let options = Options::default(); + + // This is a closure that handles the error and sends diagnostics to the client using the connection + let handle_error = |result: Result<_, VerifyError>| match result { + Ok(res) => res, + Err(e) => { + if let VerifyError::Diagnostic(diagnostic) = e { + let diag = diagnostic.into_lsp_diagnostic(); + let _ = + push_diagnostics(connection, Url::from_file_path(path).unwrap(), vec![diag]); + } + } + }; + + let mut proc_span_map: HashMap = HashMap::new(); + + // We use a block to obtain a try-catch structure to catch the VerifyErrors that might be produced by 2 different function calls. + // The closure is needed to specify the return type of the block so that we can use the '?' operator. + handle_error((|| -> Result<_, VerifyError> { + let (mut source_units, mut tcx) = + get_source_units_from_files(&options, &files_mutex, &[file_id])?; + + let files = files_mutex.lock().unwrap(); + let file = files.get(file_id).unwrap(); + + source_units.iter_mut().for_each(|item| { + let (name, source_unit) = item.enter_with_name(); + if let SourceUnit::Decl(DeclKind::ProcDecl(ref proc_ref)) = *source_unit { + proc_span_map.insert(name.clone(), proc_ref.borrow().span); + } + }); + + let mut verify_units = transform_source_to_verify(&options, source_units); + let mut local_proc_status: Vec<(lsp_types::Range, bool)> = Vec::new(); + let mut all_proven: bool = true; + for verify_unit in &mut verify_units { + let (name, mut verify_unit) = verify_unit.enter_with_name(); + + let result = verify_unit.verify(name, &mut tcx, &options)?; + + if let Some(span) = proc_span_map.get(name) { + // let char_span = files.char_span(*span); + let range = *span.to_lsp_range(*files).unwrap(); + local_proc_status.push((range, result)); + } + + all_proven = all_proven && result; + } + proc_status.clear(); + proc_status.extend(local_proc_status); + Ok(()) + })()); +} diff --git a/src/main.rs b/src/main.rs index a7cdf16..9c30851 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,48 +5,31 @@ use std::{ collections::HashMap, - fs::{create_dir_all, File}, - io::{self, Write}, + io, path::PathBuf, process::ExitCode, sync::{Arc, Mutex}, }; use crate::{ - ast::{ - stats::StatsVisitor, visit::VisitorMut, BinOpKind, ExprData, ExprKind, LitKind, Shared, - Span, Spanned, TyKind, - }, + ast::TyKind, front::{resolve::Resolve, tycheck::Tycheck}, - opt::{egraph, qelim::Qelim, relational::Relational, unfolder::Unfolder}, - smt::{translate_exprs::TranslateExprs, SmtCtx}, timing::TimingLayer, tyctx::TyCtx, - vc::{subst::apply_subst, vcgen::Vcgen}, - version::write_detailed_version_info, }; -use ast::{Diagnostic, Expr, FileId, Files, SourceFilePath}; -use driver::{Item, SourceUnit, SourceUnitName, VerifyUnit}; +use ast::{Diagnostic, FileId, Files, SourceFilePath}; +use driver::{Item, SourceUnit, VerifyUnit}; use intrinsic::{distributions::init_distributions, list::init_lists}; -use opt::{boolify::Boolify, RemoveParens}; + use procs::add_default_specs; use proof_rules::init_encodings; use resource_limits::{await_with_resource_limits, LimitError}; use thiserror::Error; use timing::DispatchBuilder; use tokio::task::JoinError; -use tracing::{info, info_span, warn}; -use z3::{ - ast::{Ast, Bool}, - Config, Context, -}; +use tracing::warn; use structopt::StructOpt; -use z3rro::{ - pretty::{get_pretty_solver_smtlib, get_solver_smtlib}, - prover::{ProveResult, Prover}, - util::{PrefixWriter, ReasonUnknown}, -}; pub mod ast; mod driver; @@ -362,8 +345,9 @@ fn verify_files_main( files_mutex: &Mutex, user_files: &[FileId], ) -> Result { - let (mut verify_units, mut tcx) = - get_verify_units_from_files(options, files_mutex, user_files)?; + let (source_units, mut tcx) = get_source_units_from_files(options, files_mutex, user_files)?; + + let mut verify_units = transform_source_to_verify(options, source_units); let mut all_proven: bool = true; for verify_unit in &mut verify_units { @@ -377,11 +361,11 @@ fn verify_files_main( Ok(all_proven) } -pub fn get_verify_units_from_files( +pub fn get_source_units_from_files( options: &Options, files_mutex: &Mutex, user_files: &[FileId], -) -> Result<(Vec>, TyCtx), VerifyError> { +) -> Result<(Vec>, TyCtx), VerifyError> { // 1. Parsing let mut source_units: Vec> = Vec::new(); let mut files = files_mutex.lock().unwrap(); @@ -460,7 +444,14 @@ pub fn get_verify_units_from_files( } } - let mut verify_units: Vec> = source_units + Ok((source_units, tcx)) +} + +fn transform_source_to_verify( + options: &Options, + source_units: Vec>, +) -> Vec> { + let verify_units: Vec> = source_units .into_iter() .flat_map(|item| item.flat_map(SourceUnit::into_verify_unit)) .collect(); @@ -469,9 +460,8 @@ pub fn get_verify_units_from_files( warn!("Z3 tracing is enabled with multiple verification units. Intermediate tracing results will be overwritten."); } - Ok((verify_units, tcx)) + verify_units } - fn setup_tracing(options: &Options) { timing::init_tracing( DispatchBuilder::default() @@ -530,157 +520,3 @@ fn load_file(files: &mut Files, path: &PathBuf) -> FileId { let file = files.add(source_file_path, source); file.id } - -fn apply_qelim(tcx: &mut TyCtx, vc_expr: &mut Expr) { - let mut qelim = Qelim::new(tcx); - qelim.qelim_inf(vc_expr); - // Apply/eliminate substitutions again - apply_subst(tcx, vc_expr); -} - -fn apply_relational_opt(vc_expr_eq_infinity: &mut Expr) { - let span = info_span!("relationalize"); - let _entered = span.enter(); - (Relational {}).visit_expr(vc_expr_eq_infinity).unwrap(); -} - -fn apply_boolify_opt(vc_expr_eq_infinity: &mut Expr) { - let span = info_span!("boolify"); - let _entered = span.enter(); - (Boolify {}).visit_expr(vc_expr_eq_infinity).unwrap(); -} - -fn unfold_expr(options: &Options, tcx: &TyCtx, vc_expr: &mut Expr) { - let span = info_span!("unfolding"); - let _entered = span.enter(); - if !options.strict { - let ctx = Context::new(&Config::default()); - let smt_ctx = SmtCtx::new(&ctx, tcx); - let mut unfolder = Unfolder::new(&smt_ctx); - unfolder.visit_expr(vc_expr).unwrap(); - } else { - apply_subst(tcx, vc_expr); - } -} - -fn mk_z3_ctx(options: &Options) -> Context { - let mut config = Config::default(); - if options.z3_trace { - config.set_bool_param_value("trace", true); - config.set_bool_param_value("proof", true); - } - Context::new(&config) -} - -fn mk_valid_query_prover<'smt, 'ctx>( - ctx: &'ctx Context, - smt_translate: &TranslateExprs<'smt, 'ctx>, - valid_query: &Bool<'ctx>, -) -> Prover<'ctx> { - // create the prover and set the params - let mut prover = Prover::new(ctx); - // add assumptions (from axioms and locals) to the prover - smt_translate - .ctx - .uninterpreteds() - .add_axioms_to_prover(&mut prover); - smt_translate - .local_scope() - .add_assumptions_to_prover(&mut prover); - // add the provable: is this Boolean true? - prover.add_provable(valid_query); - prover -} - -fn trace_expr_stats(vc_expr: &mut Expr) { - let mut stats = StatsVisitor::default(); - stats.visit_expr(vc_expr).unwrap(); - let stats = stats.stats; - tracing::info!( - num_exprs = stats.num_exprs, - num_quants = stats.num_quants, - depths = %stats.depths_summary(), - "Verification condition stats" - ); - if stats.num_quants > 0 { - tracing::warn!( - num_quants=stats.num_quants, "Quantifiers are present in the generated verification conditions. It is possible that quantifier elimination failed. If Z3 can't decide the problem, this may be the reason." - ); - } -} - -fn expr_eq_infty(vc_expr: Expr) -> Expr { - let infinity = Shared::new(ExprData { - kind: ExprKind::Lit(Spanned::with_dummy_span(LitKind::Infinity)), - ty: Some(TyKind::EUReal), - span: Span::dummy_span(), - }); - Shared::new(ExprData { - kind: ExprKind::Binary(Spanned::with_dummy_span(BinOpKind::Eq), infinity, vc_expr), - ty: Some(TyKind::Bool), - span: Span::dummy_span(), - }) -} - -fn print_prove_result(result: ProveResult, name: &SourceUnitName, prover: &Prover) { - match result { - ProveResult::Proof => println!("{}: Verified.", name), - ProveResult::Counterexample => { - println!("{}: Counter-example to verification found!", name); - if let Some(model) = prover.get_model() { - println!("{:?}", model); - }; - } - ProveResult::Unknown => { - if let Some(reason) = prover.get_reason_unknown() { - println!("{}: Unknown result! (reason: {})", name, reason) - } else { - println!("{}: Unknown result!", name) - } - } - } -} - -fn get_smtlib(options: &Options, prover: &Prover) -> Option { - if options.print_smt || options.smt_dir.is_some() { - let smtlib = if !options.no_pretty_smtlib { - get_pretty_solver_smtlib(prover.solver()) - } else { - get_solver_smtlib(prover.solver()) - }; - Some(smtlib) - } else { - None - } -} - -fn write_smtlib( - options: &Options, - smtlib: Option, - name: &SourceUnitName, - result: ProveResult, -) -> io::Result<()> { - if options.print_smt || options.smt_dir.is_some() { - let mut smtlib = smtlib.unwrap(); - if result == ProveResult::Counterexample { - smtlib.push_str("\n(get-model)\n"); - } else if result == ProveResult::Unknown { - smtlib.push_str("\n(get-info :reason-unknown)\n"); - } - if options.print_smt { - println!("\n; --- Solver SMT-LIB ---\n{}\n", smtlib); - } - if let Some(smt_dir) = &options.smt_dir { - let file_path = smt_dir.join(format!("{}.smt2", name)); - create_dir_all(file_path.parent().unwrap())?; - let mut file = File::create(&file_path)?; - let mut comment_writer = PrefixWriter::new("; ".as_bytes(), &mut file); - write_detailed_version_info(&mut comment_writer)?; - writeln!(comment_writer, "Source unit: {}", name)?; - writeln!(comment_writer, "Prove result: {:?}", result)?; - file.write_all(smtlib.as_bytes())?; - info!(?file_path, "SMT-LIB query written to file"); - } - } - Ok(()) -} diff --git a/src/procs/spec_call.rs b/src/procs/spec_call.rs index 5ca7bb2..2e0ba01 100644 --- a/src/procs/spec_call.rs +++ b/src/procs/spec_call.rs @@ -225,7 +225,7 @@ mod test { assert ?(false) // this should never verify! } "#; - let res = verify_test(&source).0.unwrap(); + let res = verify_test(source).0.unwrap(); assert_eq!(res, false); } } From 1a03c5427fe78c3a1121343a40ce274d591c6f3d Mon Sep 17 00:00:00 2001 From: umutdural Date: Sat, 6 Apr 2024 14:51:15 +0200 Subject: [PATCH 03/25] vscode-ext: working prototype for checkmarks and diagnostics --- caesar-ext/out/extension.js | 93 ++++++++---- caesar-ext/out/extension.js.map | 2 +- caesar-ext/package-lock.json | 58 ++++++- caesar-ext/package.json | 18 ++- caesar-ext/src/extension.ts | 114 ++++++++++---- src/ast/diagnostic.rs | 25 ++- ...uage_server_main.rs => language_server.rs} | 143 +++++++++++++----- src/language_server/mod.rs | 2 +- src/main.rs | 18 ++- 9 files changed, 365 insertions(+), 108 deletions(-) rename src/language_server/{language_server_main.rs => language_server.rs} (67%) diff --git a/caesar-ext/out/extension.js b/caesar-ext/out/extension.js index 8b93a5f..f74a6b0 100644 --- a/caesar-ext/out/extension.js +++ b/caesar-ext/out/extension.js @@ -27,47 +27,82 @@ exports.deactivate = exports.activate = void 0; // The module 'vscode' contains the VS Code extensibility API // Import the module and reference it with the alias vscode in your code below const vscode = __importStar(require("vscode")); +const path = __importStar(require("path")); +const os = __importStar(require("os")); +const node_1 = require("vscode-languageclient/node"); +let client; // This method is called when your extension is activated // Your extension is activated the very first time the command is executed function activate(context) { + let serverExecutable = "cargo"; + // If the extension is launched in debug mode then the debug server options are used + // Otherwise the run options are used + let serverOptions = { + run: { + command: serverExecutable, + args: ['run', '--', '--language-server'], + options: { cwd: path.resolve(os.homedir(), 'caesar') }, + }, + debug: { + command: serverExecutable, + args: ['run', '--', '--language-server'], + options: { cwd: path.resolve(os.homedir(), 'caesar') }, + } + }; + // Options to control the language client + let clientOptions = { + diagnosticCollectionName: 'caesar', + // Register the server for heyvl documents + documentSelector: [{ scheme: 'file', language: 'heyvl' }], + synchronize: { + // Notify the server about file changes to '.clientrc files contained in the workspace + fileEvents: vscode.workspace.createFileSystemWatcher('**/*.heyvl') + } + }; + // Create the language client and start the client. + client = new node_1.LanguageClient('caesar', 'Caesar', serverOptions, clientOptions); let decorationType = vscode.window.createTextEditorDecorationType({ after: { color: new vscode.ThemeColor('editor.foreground'), backgroundColor: new vscode.ThemeColor('editor.background'), }, }); - let editor = vscode.window.activeTextEditor; - if (editor) { - updateDecorations(editor, decorationType); - } - vscode.workspace.onWillSaveTextDocument(event => { - const openEditor = vscode.window.visibleTextEditors.filter(editor => editor.document.uri === event.document.uri)[0]; - updateDecorations(openEditor, decorationType); + vscode.workspace.onDidSaveTextDocument(event => { + const openEditor = vscode.window.visibleTextEditors.filter(editor => editor.document.uri === event.uri)[0]; + getProcStatus(openEditor, decorationType, openEditor.document); }); - // Use the console to output diagnostic information (console.log) and errors (console.error) - // This line of code will only be executed once when your extension is activated + // // Start the client. This will also launch the server + client.start(); + // let editor = vscode.window.activeTextEditor; + // if (editor) { + // getProcStatus(editor, decorationType, editor.document); + // } + // // // Use the console to output diagnostic information (console.log) and errors (console.error) + // // // This line of code will only be executed once when your extension is activated console.log('Congratulations, your extension "caesar" is now active!'); - // The command has been defined in the package.json file - // Now provide the implementation of the command with registerCommand - // The commandId parameter must match the command field in package.json - let disposable = vscode.commands.registerCommand('caesar.helloWorld', () => { - // The code you place here will be executed every time your command is executed - // Display a message box to the user - vscode.window.showInformationMessage('Hello World from caesar!!!!'); - }); - context.subscriptions.push(disposable); + // // The command has been defined in the package.json file + // // Now provide the implementation of the command with registerCommand + // // The commandId parameter must match the command field in package.json + // let disposable = vscode.commands.registerCommand('caesar.helloWorld', () => { + // // The code you place here will be executed every time your command is executed + // // Display a message box to the user + // vscode.window.showInformationMessage('Hello World from caesar!!!!'); + // }); + // context.subscriptions.push(disposable); } exports.activate = activate; // This method is called when your extension is deactivated function deactivate() { } exports.deactivate = deactivate; -function updateDecorations(editor, decorationType) { +function updateDecorations(editor, decorationType, procStatus = []) { const decorations = []; - const procedures = [new vscode.Position(0, 0)]; + // const procStaus = getProcStatus(editor.document); // Assuming `procedures` is an array of procedure positions - for (const position of procedures) { - const verified = isVerified(editor.document, position); - const range = new vscode.Range(position, position.translate(0, 0)); + for (const proc of procStatus) { + const position = proc[0].start; + const verified = proc[1]; + // Put the checkmark before the proc. + const range = new vscode.Range(position, position); const decoration = { range, renderOptions: { @@ -81,8 +116,14 @@ function updateDecorations(editor, decorationType) { } editor.setDecorations(decorationType, decorations); } -function isVerified(document, position) { - // Implement logic to determine if the procedure at the given position is verified - return true; // Return true if verified, false otherwise +async function getProcStatus(editor, decorationType, document) { + let documentItem = { + uri: document.uri.toString(), + languageId: document.languageId, + version: document.version, + text: document.getText() + }; + let response = await client.sendRequest('custom/verifyStatus', { text_document: documentItem }); + updateDecorations(editor, decorationType, response); } //# sourceMappingURL=extension.js.map \ No newline at end of file diff --git a/caesar-ext/out/extension.js.map b/caesar-ext/out/extension.js.map index a3c4895..d4d1543 100644 --- a/caesar-ext/out/extension.js.map +++ b/caesar-ext/out/extension.js.map @@ -1 +1 @@ -{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6DAA6D;AAC7D,8EAA8E;AAC9E,+CAAiC;AAEjC,yDAAyD;AACzD,0EAA0E;AAC1E,SAAgB,QAAQ,CAAC,OAAgC;IAGxD,IAAI,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,8BAA8B,CAAC;QACjE,KAAK,EAAE;YACN,KAAK,EAAE,IAAI,MAAM,CAAC,UAAU,CAAC,mBAAmB,CAAC;YACjD,eAAe,EAAE,IAAI,MAAM,CAAC,UAAU,CAAC,mBAAmB,CAAC;SAC3D;KACD,CAAC,CAAC;IAEH,IAAI,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC;IAC5C,IAAI,MAAM,EAAE,CAAC;QACZ,iBAAiB,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,CAAC,SAAS,CAAC,sBAAsB,CAAC,KAAK,CAAC,EAAE;QAC/C,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,MAAM,CACzD,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,KAAK,KAAK,CAAC,QAAQ,CAAC,GAAG,CACpD,CAAC,CAAC,CAAC,CAAA;QACJ,iBAAiB,CAAC,UAAU,EAAE,cAAc,CAAC,CAAA;IAC9C,CAAC,CAAC,CAAA;IAEF,4FAA4F;IAC5F,gFAAgF;IAChF,OAAO,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;IAEvE,wDAAwD;IACxD,qEAAqE;IACrE,uEAAuE;IACvE,IAAI,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC1E,+EAA+E;QAC/E,oCAAoC;QACpC,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,6BAA6B,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AACxC,CAAC;AApCD,4BAoCC;AAED,2DAA2D;AAC3D,SAAgB,UAAU,KAAK,CAAC;AAAhC,gCAAgC;AAEhC,SAAS,iBAAiB,CAAC,MAAyB,EAAE,cAA+C;IACpG,MAAM,WAAW,GAA+B,EAAE,CAAC;IACnD,MAAM,UAAU,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/C,2DAA2D;IAC3D,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACvD,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACnE,MAAM,UAAU,GAAG;YAClB,KAAK;YACL,aAAa,EAAE;gBACd,KAAK,EAAE;oBACN,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG;oBAClC,KAAK,EAAE,IAAI,MAAM,CAAC,UAAU,CAAC,mBAAmB,CAAC;iBACjD;aACD;SACD,CAAC;QACF,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9B,CAAC;IACD,MAAM,CAAC,cAAc,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;AACpD,CAAC;AAED,SAAS,UAAU,CAAC,QAA6B,EAAE,QAAyB;IAC3E,kFAAkF;IAClF,OAAO,IAAI,CAAC,CAAC,2CAA2C;AACzD,CAAC"} \ No newline at end of file +{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/caesar-ext/package-lock.json b/caesar-ext/package-lock.json index 200e007..19925dd 100644 --- a/caesar-ext/package-lock.json +++ b/caesar-ext/package-lock.json @@ -7,6 +7,9 @@ "": { "name": "caesar", "version": "0.0.1", + "dependencies": { + "vscode-languageclient": "9.0.1" + }, "devDependencies": { "@types/mocha": "^10.0.6", "@types/node": "18.x", @@ -685,8 +688,7 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/binary-extensions": { "version": "2.2.0", @@ -701,7 +703,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -2443,7 +2444,6 @@ "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -2458,7 +2458,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -2813,6 +2812,52 @@ "node": ">=10.12.0" } }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageclient": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", + "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", + "dependencies": { + "minimatch": "^5.1.0", + "semver": "^7.3.7", + "vscode-languageserver-protocol": "3.17.5" + }, + "engines": { + "vscode": "^1.82.0" + } + }, + "node_modules/vscode-languageclient/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -2946,8 +2991,7 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yargs": { "version": "17.7.2", diff --git a/caesar-ext/package.json b/caesar-ext/package.json index ce806b5..fc42797 100644 --- a/caesar-ext/package.json +++ b/caesar-ext/package.json @@ -9,7 +9,9 @@ "categories": [ "Other" ], - "activationEvents": [], + "activationEvents": [ + "onLanguage:heyvl" + ], "main": "./out/extension.js", "contributes": { "commands": [ @@ -17,6 +19,17 @@ "command": "caesar.helloWorld", "title": "Hello World" } + ], + "languages": [ + { + "id": "heyvl", + "extensions": [ + ".heyvl" + ], + "aliases": [ + "HeyVL" + ] + } ] }, "scripts": { @@ -37,5 +50,8 @@ "typescript": "^5.3.3", "@vscode/test-cli": "^0.0.6", "@vscode/test-electron": "^2.3.9" + }, + "dependencies": { + "vscode-languageclient": "9.0.1" } } diff --git a/caesar-ext/src/extension.ts b/caesar-ext/src/extension.ts index c0b1802..5ade919 100644 --- a/caesar-ext/src/extension.ts +++ b/caesar-ext/src/extension.ts @@ -1,57 +1,109 @@ // The module 'vscode' contains the VS Code extensibility API // Import the module and reference it with the alias vscode in your code below import * as vscode from 'vscode'; +import * as path from 'path'; +import * as os from 'os'; +import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient/node'; + +let client: LanguageClient; // This method is called when your extension is activated // Your extension is activated the very first time the command is executed export function activate(context: vscode.ExtensionContext) { + let serverExecutable = "cargo" + + // If the extension is launched in debug mode then the debug server options are used + // Otherwise the run options are used + let serverOptions: ServerOptions = { + run: { + command: serverExecutable, + args: ['run', '--', '--language-server'], + options: { cwd: path.resolve(os.homedir(), 'caesar') }, + }, + debug: { + command: serverExecutable, + args: ['run', '--', '--language-server'], + options: { cwd: path.resolve(os.homedir(), 'caesar') }, + } + }; + + // Options to control the language client + let clientOptions: LanguageClientOptions = { + diagnosticCollectionName: 'caesar', + // Register the server for heyvl documents + documentSelector: [{ scheme: 'file', language: 'heyvl' }], + synchronize: { + // Notify the server about file changes to '.clientrc files contained in the workspace + fileEvents: vscode.workspace.createFileSystemWatcher('**/*.heyvl') + } + }; + + // Create the language client and start the client. + client = new LanguageClient( + 'caesar', + 'Caesar', + serverOptions, + clientOptions + ); + let decorationType = vscode.window.createTextEditorDecorationType({ after: { color: new vscode.ThemeColor('editor.foreground'), backgroundColor: new vscode.ThemeColor('editor.background'), }, - }); - let editor = vscode.window.activeTextEditor; - if (editor) { - updateDecorations(editor, decorationType); - } + }); - vscode.workspace.onWillSaveTextDocument(event => { + vscode.workspace.onDidSaveTextDocument(event => { const openEditor = vscode.window.visibleTextEditors.filter( - editor => editor.document.uri === event.document.uri + editor => editor.document.uri === event.uri )[0] - updateDecorations(openEditor, decorationType) + getProcStatus(openEditor, decorationType, openEditor.document); }) - // Use the console to output diagnostic information (console.log) and errors (console.error) - // This line of code will only be executed once when your extension is activated + + + // // Start the client. This will also launch the server + client.start(); + + // let editor = vscode.window.activeTextEditor; + // if (editor) { + // getProcStatus(editor, decorationType, editor.document); + // } + + // // // Use the console to output diagnostic information (console.log) and errors (console.error) + // // // This line of code will only be executed once when your extension is activated console.log('Congratulations, your extension "caesar" is now active!'); - // The command has been defined in the package.json file - // Now provide the implementation of the command with registerCommand - // The commandId parameter must match the command field in package.json - let disposable = vscode.commands.registerCommand('caesar.helloWorld', () => { - // The code you place here will be executed every time your command is executed - // Display a message box to the user - vscode.window.showInformationMessage('Hello World from caesar!!!!'); - }); + // // The command has been defined in the package.json file + // // Now provide the implementation of the command with registerCommand + // // The commandId parameter must match the command field in package.json + // let disposable = vscode.commands.registerCommand('caesar.helloWorld', () => { + // // The code you place here will be executed every time your command is executed + // // Display a message box to the user + // vscode.window.showInformationMessage('Hello World from caesar!!!!'); + // }); + + // context.subscriptions.push(disposable); + + - context.subscriptions.push(disposable); } // This method is called when your extension is deactivated export function deactivate() { } -function updateDecorations(editor: vscode.TextEditor, decorationType: vscode.TextEditorDecorationType) { +function updateDecorations(editor: vscode.TextEditor, decorationType: vscode.TextEditorDecorationType, procStatus: Array<[vscode.Range, boolean]> = []) { const decorations: vscode.DecorationOptions[] = []; - const procedures = [new vscode.Position(0, 0)]; + // const procStaus = getProcStatus(editor.document); // Assuming `procedures` is an array of procedure positions - for (const position of procedures) { - const verified = isVerified(editor.document, position); - const range = new vscode.Range(position, position.translate(0, 0)); + for (const proc of procStatus) { + const position = proc[0].start; + const verified = proc[1]; + // Put the checkmark before the proc. + const range = new vscode.Range(position, position); const decoration = { range, renderOptions: { @@ -66,7 +118,15 @@ function updateDecorations(editor: vscode.TextEditor, decorationType: vscode.Tex editor.setDecorations(decorationType, decorations); } -function isVerified(document: vscode.TextDocument, position: vscode.Position): boolean { - // Implement logic to determine if the procedure at the given position is verified - return true; // Return true if verified, false otherwise + +async function getProcStatus(editor: vscode.TextEditor, decorationType: vscode.TextEditorDecorationType, document: vscode.TextDocument) { + + let documentItem = { + uri: document.uri.toString(), + languageId: document.languageId, + version: document.version, + text: document.getText() + } + let response: Array<[vscode.Range, boolean]> = await client.sendRequest('custom/verifyStatus', { text_document: documentItem }); + updateDecorations(editor, decorationType, response); } diff --git a/src/ast/diagnostic.rs b/src/ast/diagnostic.rs index 3d8f165..3b1f10e 100644 --- a/src/ast/diagnostic.rs +++ b/src/ast/diagnostic.rs @@ -200,7 +200,7 @@ impl Span { } pub fn to_lsp_range(self, files: &Files) -> Option { - let file = files.get(file_id).unwrap(); + let file = files.get(self.file).unwrap(); let char_span = file.char_span(self); let mut start_line = 0; @@ -420,6 +420,27 @@ impl Diagnostic { let code_description = None; let source = None; let message = self.0.msg.unwrap_or_else(|| "(no message)".to_string()); + let related_information = self + .0 + .labels + .iter() + .flat_map(|label| { + Some(lsp_types::DiagnosticRelatedInformation { + location: lsp_types::Location { + uri: lsp_types::Url::parse( + format!( + "file://{}", + files.get(label.span.file).unwrap().path.to_string_lossy() + ) + .as_str(), + ) + .unwrap(), + range: label.span.to_lsp_range(files).unwrap(), + }, + message: label.msg.clone()?, + }) + }) + .collect::>(); lsp_types::Diagnostic { range, severity: Some(severity), @@ -427,7 +448,7 @@ impl Diagnostic { code_description, source, message, - related_information: None, + related_information: Some(related_information), tags: None, data: None, } diff --git a/src/language_server/language_server_main.rs b/src/language_server/language_server.rs similarity index 67% rename from src/language_server/language_server_main.rs rename to src/language_server/language_server.rs index 56ffe72..fa96f15 100644 --- a/src/language_server/language_server_main.rs +++ b/src/language_server/language_server.rs @@ -13,7 +13,7 @@ use std::sync::Arc; use std::sync::Mutex; use crate::ast::decl::DeclKind; -use crate::ast::{Files, Span, StoredFile}; +use crate::ast::{Files, Span}; use crate::driver::{SourceUnit, SourceUnitName}; use crate::{ get_source_units_from_files, load_file, transform_source_to_verify, Options, VerifyError, @@ -31,10 +31,11 @@ impl lsp_types::request::Request for VerificationStatusParams { const METHOD: &'static str = "custom/verifyStatus"; } -fn main() -> Result<(), Box> { +pub fn run_server(options: &Options) -> Result<(), Box> { let (connection, _) = Connection::stdio(); let server_capabilities = ServerCapabilities { text_document_sync: Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::NONE)), + ..ServerCapabilities::default() }; @@ -50,6 +51,7 @@ fn main() -> Result<(), Box> { handle_request( req, &connection, + options, &mut documents, &mut workspace_folders, &mut proc_status_map, @@ -59,6 +61,7 @@ fn main() -> Result<(), Box> { handle_notification( not, &connection, + options, &mut documents, &mut workspace_folders, &mut proc_status_map, @@ -74,16 +77,35 @@ fn main() -> Result<(), Box> { fn handle_request( req: Request, connection: &Connection, + options: &Options, _documents: &mut Arc>>, _workspace_folders: &mut Arc>>, - proc_status_map: &mut HashMap>, + _proc_status_map: &mut HashMap>, ) -> Result<(), Box> { let response: Response = match req.method.as_str() { - "custom/procStatus" => { + "custom/verifyStatus" => { let params: VerificationStatusParams = serde_json::from_value(req.params)?; + let uri = params.text_document.uri; - let status_vec = proc_status_map.get(&uri).unwrap(); + // TODO: Implement proper caching later. + let status_vec = match verify(options, uri.clone(), connection) { + Ok(vec) => { + let _ = clear_diagnostics(connection, uri.clone()); + vec + } + Err(_) => Vec::new(), + }; + + // let status_vec = match proc_status_map.get(&uri) { + // Some(vec) => vec, + // None => { + // verify_and_cache(options,uri.clone(), connection, proc_status_map); + // proc_status_map.get(&uri).unwrap() + // } + // }; + + eprintln!("Procs: {:?}", status_vec); let proc_status_json = serde_json::to_value(status_vec)?; Response::new_ok(req.id, proc_status_json) @@ -100,7 +122,8 @@ fn handle_request( fn handle_notification( not: lsp_server::Notification, - connection: &Connection, + _connection: &Connection, + _options: &Options, documents: &mut Arc>>, workspace_folders: &mut Arc>>, proc_status_map: &mut HashMap>, @@ -112,21 +135,21 @@ fn handle_notification( let text = params.text_document.text; documents.lock().unwrap().push((uri.to_string(), text)); - verify_and_cache(uri, connection, proc_status_map) + // verify_and_cache(options, uri, connection, proc_status_map); } "textDocument/didSave" => { let params: DidSaveTextDocumentParams = serde_json::from_value(not.params.clone())?; let uri = params.text_document.uri; let text = params.text.unwrap(); documents.lock().unwrap().push((uri.to_string(), text)); + + // verify_and_cache(uri, connection, proc_status_map); } "textDocument/didChange" => { let params: DidChangeTextDocumentParams = serde_json::from_value(not.params.clone())?; - let uri = params.text_document.uri; + let _uri = params.text_document.uri; // let _content_changes = params.content_changes; // let mut _documents = documents.lock().unwrap(); - - verify_and_cache(uri, connection, proc_status_map); } "textDocument/didClose" => { let params: DidCloseTextDocumentParams = serde_json::from_value(not.params.clone())?; @@ -134,7 +157,7 @@ fn handle_notification( documents .lock() .unwrap() - .retain(|(doc_uri, _)| !matches!(doc_uri.clone(), uri)); + .retain(|(doc_uri, _)| !matches!(doc_uri.clone(), _uri)); proc_status_map.remove(&uri); } @@ -151,7 +174,7 @@ fn handle_notification( Ok(()) } -fn push_diagnostics( +fn report_diagnostics( connection: &Connection, uri: Url, diagnostics: Vec, @@ -161,20 +184,49 @@ fn push_diagnostics( diagnostics, version: None, }; - let not = lsp_server::Notification::new("textDocument/publishDiagnostics".to_string(), params); + let notification = + lsp_server::Notification::new("textDocument/publishDiagnostics".to_string(), params); connection .sender - .send(lsp_server::Message::Notification(not))?; + .send(lsp_server::Message::Notification(notification))?; Ok(()) } -fn verify_and_cache( - uri: Url, +fn clear_diagnostics( connection: &Connection, - proc_status_map: &mut HashMap>, -) { - let proc_status = proc_status_map.entry(uri.clone()).or_default(); + uri: Url, +) -> Result<(), Box> { + let diagnostics = Vec::new(); + let params = lsp_types::PublishDiagnosticsParams { + uri, + diagnostics, + version: None, + }; + let notification = + lsp_server::Notification::new("textDocument/publishDiagnostics".to_string(), params); + connection + .sender + .send(lsp_server::Message::Notification(notification))?; + Ok(()) +} + +// fn verify_and_cache( +// options: &Options, +// uri: Url, +// connection: &Connection, +// proc_status_map: &mut HashMap>, +// ) { +// let proc_status = proc_status_map.entry(uri.clone()).or_default(); +// let local_proc_status = verify(options, uri, connection).unwrap(); +// proc_status.clear(); +// proc_status.extend(local_proc_status); +// } +fn verify( + options: &Options, + uri: Url, + connection: &Connection, +) -> Result, ()> { let path = uri .to_file_path() .expect("Failed to convert URI to file path"); @@ -183,30 +235,17 @@ fn verify_and_cache( let file_id = load_file(&mut files, &path); let files_mutex = Mutex::new(files); - let options = Options::default(); - - // This is a closure that handles the error and sends diagnostics to the client using the connection - let handle_error = |result: Result<_, VerifyError>| match result { - Ok(res) => res, - Err(e) => { - if let VerifyError::Diagnostic(diagnostic) = e { - let diag = diagnostic.into_lsp_diagnostic(); - let _ = - push_diagnostics(connection, Url::from_file_path(path).unwrap(), vec![diag]); - } - } - }; let mut proc_span_map: HashMap = HashMap::new(); + let mut local_proc_status: Vec<(lsp_types::Range, bool)> = Vec::new(); // We use a block to obtain a try-catch structure to catch the VerifyErrors that might be produced by 2 different function calls. // The closure is needed to specify the return type of the block so that we can use the '?' operator. - handle_error((|| -> Result<_, VerifyError> { + let result = (|| -> Result<_, VerifyError> { let (mut source_units, mut tcx) = - get_source_units_from_files(&options, &files_mutex, &[file_id])?; + get_source_units_from_files(options, &files_mutex, &[file_id])?; let files = files_mutex.lock().unwrap(); - let file = files.get(file_id).unwrap(); source_units.iter_mut().for_each(|item| { let (name, source_unit) = item.enter_with_name(); @@ -215,24 +254,44 @@ fn verify_and_cache( } }); - let mut verify_units = transform_source_to_verify(&options, source_units); - let mut local_proc_status: Vec<(lsp_types::Range, bool)> = Vec::new(); + eprintln!("Extracted source_unit spans"); + + let mut verify_units = transform_source_to_verify(options, source_units); + + eprintln!("Transformed into verify units"); let mut all_proven: bool = true; for verify_unit in &mut verify_units { let (name, mut verify_unit) = verify_unit.enter_with_name(); - let result = verify_unit.verify(name, &mut tcx, &options)?; + eprintln!("Verifying: {:?}", name); + let result = verify_unit.verify(name, &mut tcx, options)?; + + eprintln!("Verify Result: {}", result); if let Some(span) = proc_span_map.get(name) { // let char_span = files.char_span(*span); - let range = *span.to_lsp_range(*files).unwrap(); + let range = (*span).to_lsp_range(&files).unwrap(); local_proc_status.push((range, result)); } + eprintln!("One verified"); all_proven = all_proven && result; } - proc_status.clear(); - proc_status.extend(local_proc_status); Ok(()) - })()); + })(); + + match result { + Ok(res) => res, + Err(e) => { + if let VerifyError::Diagnostic(diagnostic) = e { + let files = files_mutex.lock().unwrap(); + let diag = diagnostic.into_lsp_diagnostic(&files); + let _ = + report_diagnostics(connection, Url::from_file_path(path).unwrap(), vec![diag]); + return Err(()); + } + } + } + + Ok(local_proc_status) } diff --git a/src/language_server/mod.rs b/src/language_server/mod.rs index cb6ffa8..5c6cb9b 100644 --- a/src/language_server/mod.rs +++ b/src/language_server/mod.rs @@ -1 +1 @@ -pub mod language_server_main; +pub mod language_server; diff --git a/src/main.rs b/src/main.rs index 9c30851..adef37a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,6 +21,7 @@ use ast::{Diagnostic, FileId, Files, SourceFilePath}; use driver::{Item, SourceUnit, VerifyUnit}; use intrinsic::{distributions::init_distributions, list::init_lists}; +use language_server::language_server::run_server; use procs::add_default_specs; use proof_rules::init_encodings; use resource_limits::{await_with_resource_limits, LimitError}; @@ -153,6 +154,10 @@ pub struct Options { /// standard output. #[structopt(long)] pub print_label_vc: bool, + + /// Run the language server. + #[structopt(long)] + pub language_server: bool, } #[tokio::main] @@ -167,11 +172,21 @@ async fn main() -> ExitCode { let mut stdout = io::stdout().lock(); version::write_detailed_version_info(&mut stdout).unwrap(); } - // install global collector configured based on RUST_LOG env var. setup_tracing(&options); let (timeout, mem_limit) = (options.timeout, options.mem_limit); + + // Run the language server and exit after it's done. + if options.language_server { + let result = run_server(&options); + if result.is_err() { + eprintln!("Error: {}", result.err().unwrap()); + return ExitCode::from(1); + } + return ExitCode::from(0); + } + if options.files.is_empty() { eprintln!("Error: list of files must not be empty.\n"); return ExitCode::from(1); @@ -186,6 +201,7 @@ async fn main() -> ExitCode { let options = Arc::new(options); let files = Arc::new(Mutex::new(files)); + let verify_result = verify_files(&options, &files, user_files).await; if options.timing { From 85944a19e94da4edeb02f3004f26001af94bd1b6 Mon Sep 17 00:00:00 2001 From: umutdural Date: Wed, 10 Apr 2024 22:18:04 +0200 Subject: [PATCH 04/25] vscode-ext: fix printing to stdio --- src/driver.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index a2980b5..8ba71bf 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -435,8 +435,10 @@ impl VerifyUnit { drop(sat_entered); drop(sat_span); - // Now let's examine the result. - print_prove_result(result, name, &prover); + if !options.language_server { + // Now let's examine the result. + print_prove_result(result, name, &prover); + } write_smtlib(options, smtlib, name, result).unwrap(); From 150515f0a431ac5415a97f470a3ea1e438cefc15 Mon Sep 17 00:00:00 2001 From: umutdural Date: Wed, 10 Apr 2024 22:44:00 +0200 Subject: [PATCH 05/25] vscode-ext: added out to gitignore --- .gitignore | 1 + caesar-ext/out/extension.js | 129 ---------------------- caesar-ext/out/extension.js.map | 1 - caesar-ext/out/test/extension.test.js | 38 ------- caesar-ext/out/test/extension.test.js.map | 1 - 5 files changed, 1 insertion(+), 169 deletions(-) delete mode 100644 caesar-ext/out/extension.js delete mode 100644 caesar-ext/out/extension.js.map delete mode 100644 caesar-ext/out/test/extension.test.js delete mode 100644 caesar-ext/out/test/extension.test.js.map diff --git a/.gitignore b/.gitignore index d48711d..afbddd5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ target .DS_Store benchmark-results.csv vscode-ext/node_modules/ +caesar-ext/out/ node_modules/ # .dockerignore is symlinked to the .gitignore, so this line is useful: .git diff --git a/caesar-ext/out/extension.js b/caesar-ext/out/extension.js deleted file mode 100644 index f74a6b0..0000000 --- a/caesar-ext/out/extension.js +++ /dev/null @@ -1,129 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.deactivate = exports.activate = void 0; -// The module 'vscode' contains the VS Code extensibility API -// Import the module and reference it with the alias vscode in your code below -const vscode = __importStar(require("vscode")); -const path = __importStar(require("path")); -const os = __importStar(require("os")); -const node_1 = require("vscode-languageclient/node"); -let client; -// This method is called when your extension is activated -// Your extension is activated the very first time the command is executed -function activate(context) { - let serverExecutable = "cargo"; - // If the extension is launched in debug mode then the debug server options are used - // Otherwise the run options are used - let serverOptions = { - run: { - command: serverExecutable, - args: ['run', '--', '--language-server'], - options: { cwd: path.resolve(os.homedir(), 'caesar') }, - }, - debug: { - command: serverExecutable, - args: ['run', '--', '--language-server'], - options: { cwd: path.resolve(os.homedir(), 'caesar') }, - } - }; - // Options to control the language client - let clientOptions = { - diagnosticCollectionName: 'caesar', - // Register the server for heyvl documents - documentSelector: [{ scheme: 'file', language: 'heyvl' }], - synchronize: { - // Notify the server about file changes to '.clientrc files contained in the workspace - fileEvents: vscode.workspace.createFileSystemWatcher('**/*.heyvl') - } - }; - // Create the language client and start the client. - client = new node_1.LanguageClient('caesar', 'Caesar', serverOptions, clientOptions); - let decorationType = vscode.window.createTextEditorDecorationType({ - after: { - color: new vscode.ThemeColor('editor.foreground'), - backgroundColor: new vscode.ThemeColor('editor.background'), - }, - }); - vscode.workspace.onDidSaveTextDocument(event => { - const openEditor = vscode.window.visibleTextEditors.filter(editor => editor.document.uri === event.uri)[0]; - getProcStatus(openEditor, decorationType, openEditor.document); - }); - // // Start the client. This will also launch the server - client.start(); - // let editor = vscode.window.activeTextEditor; - // if (editor) { - // getProcStatus(editor, decorationType, editor.document); - // } - // // // Use the console to output diagnostic information (console.log) and errors (console.error) - // // // This line of code will only be executed once when your extension is activated - console.log('Congratulations, your extension "caesar" is now active!'); - // // The command has been defined in the package.json file - // // Now provide the implementation of the command with registerCommand - // // The commandId parameter must match the command field in package.json - // let disposable = vscode.commands.registerCommand('caesar.helloWorld', () => { - // // The code you place here will be executed every time your command is executed - // // Display a message box to the user - // vscode.window.showInformationMessage('Hello World from caesar!!!!'); - // }); - // context.subscriptions.push(disposable); -} -exports.activate = activate; -// This method is called when your extension is deactivated -function deactivate() { } -exports.deactivate = deactivate; -function updateDecorations(editor, decorationType, procStatus = []) { - const decorations = []; - // const procStaus = getProcStatus(editor.document); - // Assuming `procedures` is an array of procedure positions - for (const proc of procStatus) { - const position = proc[0].start; - const verified = proc[1]; - // Put the checkmark before the proc. - const range = new vscode.Range(position, position); - const decoration = { - range, - renderOptions: { - after: { - contentText: verified ? '✔️' : '❌', - color: new vscode.ThemeColor('editor.foreground'), - }, - }, - }; - decorations.push(decoration); - } - editor.setDecorations(decorationType, decorations); -} -async function getProcStatus(editor, decorationType, document) { - let documentItem = { - uri: document.uri.toString(), - languageId: document.languageId, - version: document.version, - text: document.getText() - }; - let response = await client.sendRequest('custom/verifyStatus', { text_document: documentItem }); - updateDecorations(editor, decorationType, response); -} -//# sourceMappingURL=extension.js.map \ No newline at end of file diff --git a/caesar-ext/out/extension.js.map b/caesar-ext/out/extension.js.map deleted file mode 100644 index d4d1543..0000000 --- a/caesar-ext/out/extension.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6DAA6D;AAC7D,8EAA8E;AAC9E,+CAAiC;AACjC,2CAA6B;AAC7B,uCAAyB;AACzB,qDAAiH;AAGjH,IAAI,MAAsB,CAAC;AAC3B,yDAAyD;AACzD,0EAA0E;AAC1E,SAAgB,QAAQ,CAAC,OAAgC;IAExD,IAAI,gBAAgB,GAAG,OAAO,CAAA;IAE9B,oFAAoF;IACpF,qCAAqC;IACrC,IAAI,aAAa,GAAkB;QAClC,GAAG,EAAE;YACJ,OAAO,EAAE,gBAAgB;YACzB,IAAI,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,mBAAmB,CAAC;YACxC,OAAO,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,EAAE;SACtD;QACD,KAAK,EAAE;YACN,OAAO,EAAE,gBAAgB;YACzB,IAAI,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,mBAAmB,CAAC;YACxC,OAAO,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,EAAE;SACtD;KACD,CAAC;IAEF,yCAAyC;IACzC,IAAI,aAAa,GAA0B;QAC1C,wBAAwB,EAAE,QAAQ;QAClC,0CAA0C;QAC1C,gBAAgB,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;QACzD,WAAW,EAAE;YACZ,sFAAsF;YACtF,UAAU,EAAE,MAAM,CAAC,SAAS,CAAC,uBAAuB,CAAC,YAAY,CAAC;SAClE;KACD,CAAC;IAEF,mDAAmD;IACnD,MAAM,GAAG,IAAI,qBAAc,CAC1B,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,aAAa,CACb,CAAC;IAGF,IAAI,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,8BAA8B,CAAC;QACjE,KAAK,EAAE;YACN,KAAK,EAAE,IAAI,MAAM,CAAC,UAAU,CAAC,mBAAmB,CAAC;YACjD,eAAe,EAAE,IAAI,MAAM,CAAC,UAAU,CAAC,mBAAmB,CAAC;SAC3D;KAED,CAAC,CAAC;IAEH,MAAM,CAAC,SAAS,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE;QAC9C,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,MAAM,CACzD,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG,CAC3C,CAAC,CAAC,CAAC,CAAA;QACJ,aAAa,CAAC,UAAU,EAAE,cAAc,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IAChE,CAAC,CAAC,CAAA;IAIF,wDAAwD;IACxD,MAAM,CAAC,KAAK,EAAE,CAAC;IAEf,+CAA+C;IAC/C,gBAAgB;IAChB,2DAA2D;IAC3D,IAAI;IAEJ,kGAAkG;IAClG,sFAAsF;IACtF,OAAO,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;IAEvE,2DAA2D;IAC3D,wEAAwE;IACxE,0EAA0E;IAC1E,gFAAgF;IAChF,mFAAmF;IACnF,wCAAwC;IACxC,wEAAwE;IACxE,MAAM;IAEN,0CAA0C;AAI3C,CAAC;AAjFD,4BAiFC;AAED,2DAA2D;AAC3D,SAAgB,UAAU,KAAK,CAAC;AAAhC,gCAAgC;AAEhC,SAAS,iBAAiB,CAAC,MAAyB,EAAE,cAA+C,EAAE,aAA6C,EAAE;IACrJ,MAAM,WAAW,GAA+B,EAAE,CAAC;IACnD,oDAAoD;IACpD,2DAA2D;IAC3D,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,qCAAqC;QACrC,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACnD,MAAM,UAAU,GAAG;YAClB,KAAK;YACL,aAAa,EAAE;gBACd,KAAK,EAAE;oBACN,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG;oBAClC,KAAK,EAAE,IAAI,MAAM,CAAC,UAAU,CAAC,mBAAmB,CAAC;iBACjD;aACD;SACD,CAAC;QACF,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9B,CAAC;IACD,MAAM,CAAC,cAAc,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;AACpD,CAAC;AAGD,KAAK,UAAU,aAAa,CAAC,MAAyB,EAAE,cAA+C,EAAE,QAA6B;IAErI,IAAI,YAAY,GAAG;QAClB,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE;QAC5B,UAAU,EAAE,QAAQ,CAAC,UAAU;QAC/B,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,IAAI,EAAE,QAAQ,CAAC,OAAO,EAAE;KACxB,CAAA;IACD,IAAI,QAAQ,GAAmC,MAAM,MAAM,CAAC,WAAW,CAAC,qBAAqB,EAAE,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC,CAAC;IAChI,iBAAiB,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,CAAC,CAAC;AACrD,CAAC"} \ No newline at end of file diff --git a/caesar-ext/out/test/extension.test.js b/caesar-ext/out/test/extension.test.js deleted file mode 100644 index 04257df..0000000 --- a/caesar-ext/out/test/extension.test.js +++ /dev/null @@ -1,38 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const assert = __importStar(require("assert")); -// You can import and use all API from the 'vscode' module -// as well as import your extension to test it -const vscode = __importStar(require("vscode")); -// import * as myExtension from '../../extension'; -suite('Extension Test Suite', () => { - vscode.window.showInformationMessage('Start all tests.'); - test('Sample test', () => { - assert.strictEqual(-1, [1, 2, 3].indexOf(5)); - assert.strictEqual(-1, [1, 2, 3].indexOf(0)); - }); -}); -//# sourceMappingURL=extension.test.js.map \ No newline at end of file diff --git a/caesar-ext/out/test/extension.test.js.map b/caesar-ext/out/test/extension.test.js.map deleted file mode 100644 index 5fe9345..0000000 --- a/caesar-ext/out/test/extension.test.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"extension.test.js","sourceRoot":"","sources":["../../src/test/extension.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAAiC;AAEjC,0DAA0D;AAC1D,8CAA8C;AAC9C,+CAAiC;AACjC,kDAAkD;AAElD,KAAK,CAAC,sBAAsB,EAAE,GAAG,EAAE;IAClC,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,kBAAkB,CAAC,CAAC;IAEzD,IAAI,CAAC,aAAa,EAAE,GAAG,EAAE;QACxB,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7C,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"} \ No newline at end of file From 761de64fbcd787575a04dfd26f104bc08f92143a Mon Sep 17 00:00:00 2001 From: umutdural Date: Thu, 18 Apr 2024 13:49:10 +0200 Subject: [PATCH 06/25] vscode-ext: Status bar and gutter information with checkmarks --- caesar-ext/images/failed.png | Bin 0 -> 292 bytes caesar-ext/images/unkown.png | Bin 0 -> 289 bytes caesar-ext/images/verified.png | Bin 0 -> 292 bytes caesar-ext/src/GutterInformationView.ts | 77 ++++++++++++++++++++ caesar-ext/src/Manager.ts | 55 ++++++++++++++ caesar-ext/src/StateManager.ts | 45 ++++++++++++ caesar-ext/src/StatusBarView.ts | 65 +++++++++++++++++ caesar-ext/src/VerificationManager.ts | 46 ++++++++++++ caesar-ext/src/extension.ts | 92 +++++++----------------- src/language_server/language_server.rs | 36 ++-------- 10 files changed, 320 insertions(+), 96 deletions(-) create mode 100644 caesar-ext/images/failed.png create mode 100644 caesar-ext/images/unkown.png create mode 100644 caesar-ext/images/verified.png create mode 100644 caesar-ext/src/GutterInformationView.ts create mode 100644 caesar-ext/src/Manager.ts create mode 100644 caesar-ext/src/StateManager.ts create mode 100644 caesar-ext/src/StatusBarView.ts create mode 100644 caesar-ext/src/VerificationManager.ts diff --git a/caesar-ext/images/failed.png b/caesar-ext/images/failed.png new file mode 100644 index 0000000000000000000000000000000000000000..f1b3107e120d40dda461fe0469147c31b384515a GIT binary patch literal 292 zcmV+<0o(qGP)Px#-bqA3R7i=%mR%CUFbISRU`gzlH0l2U}Q+qONd z_)%*?HNr#>;#mYA4ze%=Y7WeT5b#%E70iRaJ*>mlHE=QCK9ZW5kkLY2p9>XFbcTJU|_Z^ zC}6hmdn+RREz{17EsLYpGF)LKh+Yo8xj=OGEL26Xo+MiqjiH}`S;6S+n*Z}3@PAv3 q)ljI3S^=ip#0)gm2%~VO)qet=Ood9ZkFvx70000Px#+et)0R7i=%meCEuFbqVUs58)2V6=7s7>%w1OTd>=2@bxqBlSL$$S-F*ii;3> zT+c6SeO|YM#&8ezAU%2Tznd%!ftnjV&}q4wL7uk@4E|ZLU_B55ZlTqKF|sb!#+=w7 ztqat>>f;b`XQd3ez&>_GVOc4odIx(Q7?oSY(aJSL?gTv{V3)qnBpb3~w#F5Q2^$E8%oxMba#Kop7y n8lpyk=`k?_O%1{*oEi1s?f`TXLhZvi00000NkvXXu0mjf-VJlY literal 0 HcmV?d00001 diff --git a/caesar-ext/images/verified.png b/caesar-ext/images/verified.png new file mode 100644 index 0000000000000000000000000000000000000000..c6f36de7417dfd8ca89c5b85526fd6905f3d3819 GIT binary patch literal 292 zcmV+<0o(qGP)Px#-bqA3R7i=%*4+(+APfNDVs0RF8^}1uaSY>l8yGh7o-qFO7fbAuiuRML*Z|5H zmwuzhQp`bt`@CsQZ1;q{r&@d4RRsAH`HPP0000 { this.receiveVerificationUpdate(update) }); + this.verifyDecType = vscode.window.createTextEditorDecorationType({ gutterIconSize: "contain", gutterIconPath: context.asAbsolutePath('images/verified.png') }); + this.failedDecType = vscode.window.createTextEditorDecorationType({ gutterIconSize: "contain", gutterIconPath: context.asAbsolutePath('images/failed.png') }); + this.unknownDecType = vscode.window.createTextEditorDecorationType({ gutterIconSize: "contain", gutterIconPath: context.asAbsolutePath('images/unknown.png') }); + } + + private receiveVerificationUpdate(newStatus: VerificationStatus) { + // Update the decorations + const editor = vscode.window.activeTextEditor; + if (editor) { + this.updateDecorations(editor, newStatus); + } + } + + + private updateDecorations(editor: vscode.TextEditor, procStatus: VerificationStatus = []) { + const verifiedProcs: vscode.DecorationOptions[] = []; + const failedProcs: vscode.DecorationOptions[] = []; + const unknownProcs: vscode.DecorationOptions[] = []; + + for (const proc of procStatus) { + const verified = proc[1]; + + const line = proc[0].start.line; + const range = new vscode.Range(line, 0, line, 0); + if (verified) { + // Put the checkmark before the proc. + verifiedProcs.push({ range, hoverMessage: 'Verified' }); + } else { + // Put the X before the proc. + failedProcs.push({ range, hoverMessage: 'Not Verified' }); + } + } + editor.setDecorations(this.verifyDecType, verifiedProcs); + editor.setDecorations(this.failedDecType, failedProcs); + editor.setDecorations(this.unknownDecType, unknownProcs); + } + + + public dispose() { + this.verifyDecType.dispose(); + this.failedDecType.dispose(); + this.unknownDecType.dispose(); + } + +} + + + diff --git a/caesar-ext/src/Manager.ts b/caesar-ext/src/Manager.ts new file mode 100644 index 0000000..0f0353b --- /dev/null +++ b/caesar-ext/src/Manager.ts @@ -0,0 +1,55 @@ +// Parent class for Observer-pattern Subjects which we call Managers +export class Manager { + // Observer-pattern subject + + private observers: Observer[] = [] + + /// Notify the observers with the latest verification status + public notify(update: any) { + this.observers.forEach(observer => observer.receiveUpdate(update)); + } + + /// Subscribe an observer to the VerificationManager + public subscribe(o: Observer) { + if (this.observers.includes(o)) { + return; + } + this.observers.push(o); + } + + /// Subscribe multiple observers to the VerificationManager + public subscribeMany(o: Array) { + o.forEach(observer => this.subscribe(observer)); + } + + /// Unsubscribe an observer from the VerificationManager + public unsubscribe(o: Observer) { + const index = this.observers.indexOf(o); + if (index === -1) { + return; + } + this.observers.splice(index, 1); + } +} + + +export class Observer { + + private callback: (update: any) => void; + private manager: Manager; + + public constructor(manager: Manager, callback: (update: any) => void) { + this.callback = callback; + this.manager = manager; + + this.manager.subscribe(this); + } + + public receiveUpdate(update: any): void { + this.callback(update); + } +} + + + + diff --git a/caesar-ext/src/StateManager.ts b/caesar-ext/src/StateManager.ts new file mode 100644 index 0000000..b34f296 --- /dev/null +++ b/caesar-ext/src/StateManager.ts @@ -0,0 +1,45 @@ + +import * as vscode from "vscode"; +import { LanguageClient } from "vscode-languageclient/node"; +import { Manager, Observer } from "./Manager"; + + +export enum State { + Starting, + Ready, + FailedToStart, + Verifying, + Finished, +} + + +// Subject +export class StateManager extends Manager { + + private client: LanguageClient; + + private state: State = State.Starting; + + constructor(client: LanguageClient) { + super(); + this.client = client; + + client.onNotification("custom/serverReady", () => { + this.setState(State.Ready); + }) + } + + + public setState(state: State) { + this.state = state; + this.notify(state); + } + + public getState(): State { + return this.state; + } + +} + + + diff --git a/caesar-ext/src/StatusBarView.ts b/caesar-ext/src/StatusBarView.ts new file mode 100644 index 0000000..4739d84 --- /dev/null +++ b/caesar-ext/src/StatusBarView.ts @@ -0,0 +1,65 @@ +import * as vscode from "vscode"; +import { VerificationStatus } from "./VerificationManager"; +import { Manager, Observer } from "./Manager"; +import { State, StateManager } from "./StateManager"; + + +export class StatusBarView { + + private stateObserver: Observer; + + private statusBarItems: Array; + private progressText: vscode.StatusBarItem; + + constructor(stateManager: StateManager) { + + this.stateObserver = new Observer(stateManager, (update: State) => { this.receiveStateUpdate(update) }); + + this.statusBarItems = []; + + this.progressText = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 99); + this.progressText.text = "caesar"; + this.progressText.tooltip = "Caesar verification status"; + + this.statusBarItems.push(this.progressText); + + this.showStatusBar(); + } + + public showStatusBar() { + for (const statusBarItem of this.statusBarItems) { + statusBarItem.show(); + } + } + + public dispose() { + for (const statusBarItem of this.statusBarItems) { + statusBarItem.dispose(); + } + } + + private receiveStateUpdate(p: State) { + switch (p) { + case State.Starting: + this.progressText.text = StatusBarText.Starting; + break; + case State.Ready: + this.progressText.text = StatusBarText.Ready; + break; + case State.Verifying: + this.progressText.text = StatusBarText.Verifying; + break; + case State.Finished: + this.progressText.text = StatusBarText.Verified; + break; + } + } +} + + +export enum StatusBarText { + Starting = "$(sync~spin) Starting Caesar...", + Ready = "$(check) Caesar Ready", + Verifying = "$(sync~spin) Verifying...", + Verified = "$(check) Verified" +} diff --git a/caesar-ext/src/VerificationManager.ts b/caesar-ext/src/VerificationManager.ts new file mode 100644 index 0000000..7abceb2 --- /dev/null +++ b/caesar-ext/src/VerificationManager.ts @@ -0,0 +1,46 @@ + +import * as vscode from "vscode"; +import { LanguageClient } from "vscode-languageclient/node"; +import { Manager, Observer } from "./Manager"; + + +export type VerificationStatus = Array<[vscode.Range, boolean]>; + +// Subject +export class VerificationManager extends Manager { + + private client: LanguageClient; + + private verificationStatus: VerificationStatus = []; + + + + constructor(client: LanguageClient) { + super(); + this.client = client; + } + + public getStatus(): VerificationStatus { + return this.verificationStatus; + } + + public setStatus(newStatus: VerificationStatus): void { + this.verificationStatus = newStatus; + this.notify(newStatus); + } + + + public async verify(editor: vscode.TextEditor, document: vscode.TextDocument): Promise { + let documentItem = { + uri: document.uri.toString(), + languageId: document.languageId, + version: document.version, + text: document.getText() + } + let response: VerificationStatus = await this.client.sendRequest('custom/verifyStatus', { text_document: documentItem }); + this.setStatus(response); + return response; + } + +} + diff --git a/caesar-ext/src/extension.ts b/caesar-ext/src/extension.ts index 5ade919..b8eb70d 100644 --- a/caesar-ext/src/extension.ts +++ b/caesar-ext/src/extension.ts @@ -4,6 +4,10 @@ import * as vscode from 'vscode'; import * as path from 'path'; import * as os from 'os'; import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient/node'; +import { VerificationManager } from './VerificationManager'; +import { GutterInformationView } from './GutterInformationView'; +import { StatusBarView } from './StatusBarView'; +import { State, StateManager } from './StateManager'; let client: LanguageClient; @@ -48,85 +52,43 @@ export function activate(context: vscode.ExtensionContext) { ); - let decorationType = vscode.window.createTextEditorDecorationType({ - after: { - color: new vscode.ThemeColor('editor.foreground'), - backgroundColor: new vscode.ThemeColor('editor.background'), - }, + // Initialize Managers + let verificationManager = new VerificationManager(client); + let stateManager = new StateManager(client); + + // Initialize UI Views + let gutterInfo = new GutterInformationView(verificationManager, context); + let statusBar = new StatusBarView(stateManager); - }); vscode.workspace.onDidSaveTextDocument(event => { + if (stateManager.getState() === State.Starting) { + return + } const openEditor = vscode.window.visibleTextEditors.filter( editor => editor.document.uri === event.uri )[0] - getProcStatus(openEditor, decorationType, openEditor.document); - }) + stateManager.setState(State.Verifying); + console.log("Verification Started") + verificationManager.verify(openEditor, openEditor.document).then((_) => { + stateManager.setState(State.Finished) + } + ) + }); - // // Start the client. This will also launch the server + // Start the client. This will also launch the server client.start(); - // let editor = vscode.window.activeTextEditor; - // if (editor) { - // getProcStatus(editor, decorationType, editor.document); - // } - - // // // Use the console to output diagnostic information (console.log) and errors (console.error) - // // // This line of code will only be executed once when your extension is activated - console.log('Congratulations, your extension "caesar" is now active!'); - - // // The command has been defined in the package.json file - // // Now provide the implementation of the command with registerCommand - // // The commandId parameter must match the command field in package.json - // let disposable = vscode.commands.registerCommand('caesar.helloWorld', () => { - // // The code you place here will be executed every time your command is executed - // // Display a message box to the user - // vscode.window.showInformationMessage('Hello World from caesar!!!!'); - // }); - - // context.subscriptions.push(disposable); - + console.log('Caesar is now active!'); + context.subscriptions.push(statusBar); + context.subscriptions.push(gutterInfo); + context.subscriptions.push(client); } -// This method is called when your extension is deactivated +// This method is called when the extension is deactivated export function deactivate() { } -function updateDecorations(editor: vscode.TextEditor, decorationType: vscode.TextEditorDecorationType, procStatus: Array<[vscode.Range, boolean]> = []) { - const decorations: vscode.DecorationOptions[] = []; - // const procStaus = getProcStatus(editor.document); - // Assuming `procedures` is an array of procedure positions - for (const proc of procStatus) { - const position = proc[0].start; - const verified = proc[1]; - // Put the checkmark before the proc. - const range = new vscode.Range(position, position); - const decoration = { - range, - renderOptions: { - after: { - contentText: verified ? '✔️' : '❌', - color: new vscode.ThemeColor('editor.foreground'), - }, - }, - }; - decorations.push(decoration); - } - editor.setDecorations(decorationType, decorations); -} - - -async function getProcStatus(editor: vscode.TextEditor, decorationType: vscode.TextEditorDecorationType, document: vscode.TextDocument) { - - let documentItem = { - uri: document.uri.toString(), - languageId: document.languageId, - version: document.version, - text: document.getText() - } - let response: Array<[vscode.Range, boolean]> = await client.sendRequest('custom/verifyStatus', { text_document: documentItem }); - updateDecorations(editor, decorationType, response); -} diff --git a/src/language_server/language_server.rs b/src/language_server/language_server.rs index fa96f15..f2f9298 100644 --- a/src/language_server/language_server.rs +++ b/src/language_server/language_server.rs @@ -45,6 +45,11 @@ pub fn run_server(options: &Options) -> Result<(), Box> let mut workspace_folders = Arc::new(Mutex::new(Vec::new())); let mut proc_status_map: HashMap> = HashMap::new(); + let start_notification = lsp_server::Notification::new("custom/serverReady".to_string(), {}); + let _ = connection + .sender + .send(Message::Notification(start_notification)); + for msg in &connection.receiver { match msg { Message::Request(req) => { @@ -97,16 +102,6 @@ fn handle_request( Err(_) => Vec::new(), }; - // let status_vec = match proc_status_map.get(&uri) { - // Some(vec) => vec, - // None => { - // verify_and_cache(options,uri.clone(), connection, proc_status_map); - // proc_status_map.get(&uri).unwrap() - // } - // }; - - eprintln!("Procs: {:?}", status_vec); - let proc_status_json = serde_json::to_value(status_vec)?; Response::new_ok(req.id, proc_status_json) } @@ -210,18 +205,6 @@ fn clear_diagnostics( Ok(()) } -// fn verify_and_cache( -// options: &Options, -// uri: Url, -// connection: &Connection, -// proc_status_map: &mut HashMap>, -// ) { -// let proc_status = proc_status_map.entry(uri.clone()).or_default(); -// let local_proc_status = verify(options, uri, connection).unwrap(); -// proc_status.clear(); -// proc_status.extend(local_proc_status); -// } - fn verify( options: &Options, uri: Url, @@ -254,26 +237,17 @@ fn verify( } }); - eprintln!("Extracted source_unit spans"); - let mut verify_units = transform_source_to_verify(options, source_units); - - eprintln!("Transformed into verify units"); let mut all_proven: bool = true; for verify_unit in &mut verify_units { let (name, mut verify_unit) = verify_unit.enter_with_name(); - - eprintln!("Verifying: {:?}", name); let result = verify_unit.verify(name, &mut tcx, options)?; - eprintln!("Verify Result: {}", result); - if let Some(span) = proc_span_map.get(name) { // let char_span = files.char_span(*span); let range = (*span).to_lsp_range(&files).unwrap(); local_proc_status.push((range, result)); } - eprintln!("One verified"); all_proven = all_proven && result; } From e96b93970b96cdaef4247cc6bf39fa92493d6086 Mon Sep 17 00:00:00 2001 From: umutdural Date: Tue, 7 May 2024 23:36:09 +0200 Subject: [PATCH 07/25] vscode-ext: merged old extension with new --- caesar-ext/language-configuration.json | 30 ++++++++ caesar-ext/package.json | 24 +++--- caesar-ext/syntaxes/heyvl.tmLanguage.json | 93 +++++++++++++++++++++++ 3 files changed, 135 insertions(+), 12 deletions(-) create mode 100644 caesar-ext/language-configuration.json create mode 100644 caesar-ext/syntaxes/heyvl.tmLanguage.json diff --git a/caesar-ext/language-configuration.json b/caesar-ext/language-configuration.json new file mode 100644 index 0000000..5984db8 --- /dev/null +++ b/caesar-ext/language-configuration.json @@ -0,0 +1,30 @@ +{ + "comments": { + // symbol used for single line comment. + "lineComment": "//", + // symbols used for start and end a block comment. + "blockComment": [ "/*", "*/" ] + }, + // symbols used as brackets + "brackets": [ + ["{", "}"], + ["[", "]"], + ["(", ")"] + ], + // symbols that are auto closed when typing + "autoClosingPairs": [ + ["{", "}"], + ["[", "]"], + ["(", ")"], + ["\"", "\""], + ["'", "'"] + ], + // symbols that can be used to surround a selection + "surroundingPairs": [ + ["{", "}"], + ["[", "]"], + ["(", ")"], + ["\"", "\""], + ["'", "'"] + ] +} \ No newline at end of file diff --git a/caesar-ext/package.json b/caesar-ext/package.json index fc42797..16d6300 100644 --- a/caesar-ext/package.json +++ b/caesar-ext/package.json @@ -9,26 +9,26 @@ "categories": [ "Other" ], - "activationEvents": [ - "onLanguage:heyvl" - ], "main": "./out/extension.js", "contributes": { - "commands": [ - { - "command": "caesar.helloWorld", - "title": "Hello World" - } - ], "languages": [ { "id": "heyvl", + "aliases": [ + "HeyVL", + "heyvl" + ], "extensions": [ ".heyvl" ], - "aliases": [ - "HeyVL" - ] + "configuration": "./language-configuration.json" + } + ], + "grammars": [ + { + "language": "heyvl", + "scopeName": "source.heyvl", + "path": "./syntaxes/heyvl.tmLanguage.json" } ] }, diff --git a/caesar-ext/syntaxes/heyvl.tmLanguage.json b/caesar-ext/syntaxes/heyvl.tmLanguage.json new file mode 100644 index 0000000..a12d646 --- /dev/null +++ b/caesar-ext/syntaxes/heyvl.tmLanguage.json @@ -0,0 +1,93 @@ +{ + "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", + "name": "HeyVL", + "patterns": [ + { + "include": "#keywords" + }, + { + "include": "#strings" + }, + { + "include": "#comments" + }, + { + "include": "#type" + }, + { + "include": "#constant" + } + ], + "repository": { + "keywords": { + "patterns": [ + { + "name": "keyword.control.heyvl", + "match": "\\b(var|(co)?assume|(co)?assert|(co)?negate|(co)?validate|if|else|(co)?proc|pre|post|(co)?compare|tick|reward|while|(co)?havoc|domain|func|axiom)\\b" + }, + { + "name": "keyword.operator.heyvl", + "match": "\\b(forall|exists|inf|sup|ite|let)\\b" + } + ] + }, + "type": { + "patterns": [ + { + "name": "entity.name.type", + "match": "(\\[\\])+[a-zA-Z]+\\b" + }, + { + "name": "entity.name.type", + "match": "\\b(Bool|Int|UInt|Real|UReal|EUReal)\\b" + } + ] + }, + "paren-expr": { + "begin": "\\(", + "end": "\\)", + "beginCaptures": { + "0": { + "name": "punctuation.paren.open" + } + }, + "endCaptures": { + "0": { + "name": "punctuation.paren.close" + } + }, + "name": "expression.group", + "patterns": [ + { + "include": "#expr" + } + ] + }, + "comments": { + "patterns": [ + { + "match": "/{2}.*", + "name": "comment.single.heyvl" + }, + { + "begin": "/\\*", + "end": "\\*/", + "name": "comment.block.heyvl" + } + ] + }, + "constant": { + "patterns": [ + { + "name": "constant.numeric.heyvl", + "match": "\\b[0-9]+(\\.[0-9]+)?\\b" + }, + { + "name": "constant.language.heyvl", + "match": "\\b(true|false|∞|\\\\[a-zA-Z]+)\\b" + } + ] + } + }, + "scopeName": "source.heyvl" +} From 61493b345d38a5f32d29dda84e7fff7676a0c66e Mon Sep 17 00:00:00 2001 From: umutdural Date: Tue, 7 May 2024 23:37:36 +0200 Subject: [PATCH 08/25] vscode-ext: commands,configurations,better views,lazy api register interface --- caesar-ext/package.json | 68 +++++++++ caesar-ext/src/APIRegister.ts | 42 ++++++ caesar-ext/src/Configuration.ts | 58 ++++++++ caesar-ext/src/GutterInformationView.ts | 77 ---------- caesar-ext/src/StatusBarView.ts | 65 --------- caesar-ext/src/extension.ts | 77 +++++++--- caesar-ext/src/{ => manager}/Manager.ts | 17 +++ caesar-ext/src/{ => manager}/StateManager.ts | 4 +- .../src/{ => manager}/VerificationManager.ts | 16 +- caesar-ext/src/utils.ts | 19 +++ caesar-ext/src/view/GutterInformationView.ts | 137 ++++++++++++++++++ caesar-ext/src/view/InlineGhostTextView.ts | 99 +++++++++++++ caesar-ext/src/view/StatusBarView.ts | 111 ++++++++++++++ caesar-ext/src/view/View.ts | 18 +++ caesar-ext/src/view/ViewCollection.ts | 30 ++++ src/language_server/language_server.rs | 2 +- 16 files changed, 668 insertions(+), 172 deletions(-) create mode 100644 caesar-ext/src/APIRegister.ts create mode 100644 caesar-ext/src/Configuration.ts delete mode 100644 caesar-ext/src/GutterInformationView.ts delete mode 100644 caesar-ext/src/StatusBarView.ts rename caesar-ext/src/{ => manager}/Manager.ts (82%) rename caesar-ext/src/{ => manager}/StateManager.ts (88%) rename caesar-ext/src/{ => manager}/VerificationManager.ts (67%) create mode 100644 caesar-ext/src/utils.ts create mode 100644 caesar-ext/src/view/GutterInformationView.ts create mode 100644 caesar-ext/src/view/InlineGhostTextView.ts create mode 100644 caesar-ext/src/view/StatusBarView.ts create mode 100644 caesar-ext/src/view/View.ts create mode 100644 caesar-ext/src/view/ViewCollection.ts diff --git a/caesar-ext/package.json b/caesar-ext/package.json index 16d6300..8f31983 100644 --- a/caesar-ext/package.json +++ b/caesar-ext/package.json @@ -11,6 +11,24 @@ ], "main": "./out/extension.js", "contributes": { + "commands": [ + { + "command": "caesar.restartServer", + "title": "Caesar: Restart Server" + }, + { + "command": "caesar.startServer", + "title": "Caesar: Start Server" + }, + { + "command": "caesar.stopServer", + "title": "Caesar: Stop Server" + }, + { + "command": "caesar.verify", + "title": "Caesar: Verify" + } + ], "languages": [ { "id": "heyvl", @@ -30,6 +48,56 @@ "scopeName": "source.heyvl", "path": "./syntaxes/heyvl.tmLanguage.json" } + ], + "configuration": { + "type": "object", + "title": "Caesar", + "properties": { + "caesar.uI.gutterIcons.showGutterIcons": { + "type": "boolean", + "default": true, + "description": "Specifies whether to show icons on the gutter about the verification status." + }, + "caesar.uI.inlineGhostText.showInlineGhostText": { + "type": "boolean", + "default": true, + "description": "Specifies whether to show inline ghost text about the wp/wlp/ert." + }, + "caesar.uI.statusBar.showStatusBar": { + "type": "boolean", + "default": true, + "description": "Specifies whether to show the status bar." + }, + "caesar.automaticVerification": { + "type": "string", + "default": "onsave", + "enum": [ + "never", + "onsave" + ], + "description": "Specifies when Caesar automatically verifies the file." + } + } + }, + "colors": [ + { + "id": "caesar.inlineGhostBackgroundColor", + "description": "Specifies the background color of the inline ghost texts ", + "defaults": { + "dark": "#00000000", + "light": "#00000000", + "highContrast": "#00000000" + } + }, + { + "id": "caesar.inlineGhostForegroundColor", + "description": "Specifies the foreground color of the inline ghost texts", + "defaults": { + "dark": "#99999959", + "light": "#99999959", + "highContrast": "#99999999" + } + } ] }, "scripts": { diff --git a/caesar-ext/src/APIRegister.ts b/caesar-ext/src/APIRegister.ts new file mode 100644 index 0000000..0fab726 --- /dev/null +++ b/caesar-ext/src/APIRegister.ts @@ -0,0 +1,42 @@ +import * as vscode from 'vscode'; + +export const registerFunctions: { [K: string]: Function } = { + "onDidChangeConfiguration": vscode.workspace.onDidChangeConfiguration, + "onDidChangeTextDocument": vscode.workspace.onDidChangeTextDocument, + "onDidSaveTextDocument": vscode.workspace.onDidSaveTextDocument, +} + +export type RegisterType = keyof typeof registerFunctions; + +export default class APIRegister { + + /// Store all registered callbacks in a map to submit them to vscode api later + private static callbackMap = new Map void>>(); + + + /// Register a callback to be called when the vscode api event is triggered + public static register(type: RegisterType, callback: (...args: any[]) => void): void { + this.callbackMap.has(type) ? this.callbackMap.get(type)?.push(callback) : this.callbackMap.set(type, [callback]); + } + + /// Submit all registered callbacks to vscode api + public static submitAll(): void { + + for (const type of this.callbackMap.keys()) { + if (registerFunctions[type] === undefined) { + throw new Error(`The type ${type} is not a valid registration type`); + } + + // All callbacks that we want to register to the specific event from vscode api + const callbackList = this.callbackMap.get(type)!; + + // Collect all the callbacks into one function + const totalCallback = (...args: any[]) => { callbackList.forEach((callback) => callback(...args)) }; + + // Register the function to the vscode api by calling the corresponding event registration function + registerFunctions[type](totalCallback); + } + + } + +} diff --git a/caesar-ext/src/Configuration.ts b/caesar-ext/src/Configuration.ts new file mode 100644 index 0000000..7fa58a2 --- /dev/null +++ b/caesar-ext/src/Configuration.ts @@ -0,0 +1,58 @@ +import * as vscode from 'vscode'; + +export const CONFIGURATION_SECTION = 'caesar'; + +export default class Configuration { + + /// Get a configuration value from the configuration file with the given key + public static get(key: string): any { + const val: any | undefined = vscode.workspace.getConfiguration(CONFIGURATION_SECTION).get(key) + if (val === undefined) { + throw new Error(`${key} is not defined in the configuration file`); + } + return val; + } + +} + +export class ConfigCategory { + public name: string; + private parent: ConfigCategory | null; + + + constructor(name: string, parent: ConfigCategory | null,) { + this.name = name; + this.parent = parent; + } + + /// Construct the path of the category based on its hiearchical position + public getPath(): string { + return this.parent ? this.parent.getPath() + "." + this.name : this.name; + } + + public get(key: string): any { + return Configuration.get(this.getPath() + "." + key); + } + + +} + +// Configurations +// ------------------------------------------------ + +// Root Configurations: + +export const ViewConfiguration = new ConfigCategory("uI", null); + + +// View Configurations: + +export const GutterInformationViewConfig = new ConfigCategory('gutterIcons', ViewConfiguration,); +export const StatusBarViewConfig = new ConfigCategory('statusBar', ViewConfiguration); +export const InlineGhostTextViewConfig = new ConfigCategory('inlineGhostText', ViewConfiguration); + + + + + + diff --git a/caesar-ext/src/GutterInformationView.ts b/caesar-ext/src/GutterInformationView.ts deleted file mode 100644 index 5a9b20e..0000000 --- a/caesar-ext/src/GutterInformationView.ts +++ /dev/null @@ -1,77 +0,0 @@ - -import * as vscode from "vscode"; -import { VerificationManager, VerificationStatus } from "./VerificationManager"; -import { Manager, Observer } from "./Manager"; - - -export enum VerifyStatus { - Verified, - Failed, - Unknown -} - -export enum VerificationColors { - Verified = '#66f542', - Failed = '#f23a3a', - Unknown = '#f7aa57' -} - - -export class GutterInformationView { - private verificationObserver: Observer; - - private verifyDecType: vscode.TextEditorDecorationType; - private failedDecType: vscode.TextEditorDecorationType; - private unknownDecType: vscode.TextEditorDecorationType; - - constructor(verificationManager: VerificationManager, context: vscode.ExtensionContext) { - - this.verificationObserver = new Observer(verificationManager, (update: VerificationStatus) => { this.receiveVerificationUpdate(update) }); - this.verifyDecType = vscode.window.createTextEditorDecorationType({ gutterIconSize: "contain", gutterIconPath: context.asAbsolutePath('images/verified.png') }); - this.failedDecType = vscode.window.createTextEditorDecorationType({ gutterIconSize: "contain", gutterIconPath: context.asAbsolutePath('images/failed.png') }); - this.unknownDecType = vscode.window.createTextEditorDecorationType({ gutterIconSize: "contain", gutterIconPath: context.asAbsolutePath('images/unknown.png') }); - } - - private receiveVerificationUpdate(newStatus: VerificationStatus) { - // Update the decorations - const editor = vscode.window.activeTextEditor; - if (editor) { - this.updateDecorations(editor, newStatus); - } - } - - - private updateDecorations(editor: vscode.TextEditor, procStatus: VerificationStatus = []) { - const verifiedProcs: vscode.DecorationOptions[] = []; - const failedProcs: vscode.DecorationOptions[] = []; - const unknownProcs: vscode.DecorationOptions[] = []; - - for (const proc of procStatus) { - const verified = proc[1]; - - const line = proc[0].start.line; - const range = new vscode.Range(line, 0, line, 0); - if (verified) { - // Put the checkmark before the proc. - verifiedProcs.push({ range, hoverMessage: 'Verified' }); - } else { - // Put the X before the proc. - failedProcs.push({ range, hoverMessage: 'Not Verified' }); - } - } - editor.setDecorations(this.verifyDecType, verifiedProcs); - editor.setDecorations(this.failedDecType, failedProcs); - editor.setDecorations(this.unknownDecType, unknownProcs); - } - - - public dispose() { - this.verifyDecType.dispose(); - this.failedDecType.dispose(); - this.unknownDecType.dispose(); - } - -} - - - diff --git a/caesar-ext/src/StatusBarView.ts b/caesar-ext/src/StatusBarView.ts deleted file mode 100644 index 4739d84..0000000 --- a/caesar-ext/src/StatusBarView.ts +++ /dev/null @@ -1,65 +0,0 @@ -import * as vscode from "vscode"; -import { VerificationStatus } from "./VerificationManager"; -import { Manager, Observer } from "./Manager"; -import { State, StateManager } from "./StateManager"; - - -export class StatusBarView { - - private stateObserver: Observer; - - private statusBarItems: Array; - private progressText: vscode.StatusBarItem; - - constructor(stateManager: StateManager) { - - this.stateObserver = new Observer(stateManager, (update: State) => { this.receiveStateUpdate(update) }); - - this.statusBarItems = []; - - this.progressText = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 99); - this.progressText.text = "caesar"; - this.progressText.tooltip = "Caesar verification status"; - - this.statusBarItems.push(this.progressText); - - this.showStatusBar(); - } - - public showStatusBar() { - for (const statusBarItem of this.statusBarItems) { - statusBarItem.show(); - } - } - - public dispose() { - for (const statusBarItem of this.statusBarItems) { - statusBarItem.dispose(); - } - } - - private receiveStateUpdate(p: State) { - switch (p) { - case State.Starting: - this.progressText.text = StatusBarText.Starting; - break; - case State.Ready: - this.progressText.text = StatusBarText.Ready; - break; - case State.Verifying: - this.progressText.text = StatusBarText.Verifying; - break; - case State.Finished: - this.progressText.text = StatusBarText.Verified; - break; - } - } -} - - -export enum StatusBarText { - Starting = "$(sync~spin) Starting Caesar...", - Ready = "$(check) Caesar Ready", - Verifying = "$(sync~spin) Verifying...", - Verified = "$(check) Verified" -} diff --git a/caesar-ext/src/extension.ts b/caesar-ext/src/extension.ts index b8eb70d..a3e4717 100644 --- a/caesar-ext/src/extension.ts +++ b/caesar-ext/src/extension.ts @@ -4,10 +4,13 @@ import * as vscode from 'vscode'; import * as path from 'path'; import * as os from 'os'; import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient/node'; -import { VerificationManager } from './VerificationManager'; -import { GutterInformationView } from './GutterInformationView'; -import { StatusBarView } from './StatusBarView'; -import { State, StateManager } from './StateManager'; +import { VerificationManager } from './manager/VerificationManager'; +import { GutterInformationView } from './view/GutterInformationView'; +import { StatusBarView } from './view/StatusBarView'; +import { State, StateManager } from './manager/StateManager'; +import { InlineGhostTextView } from './view/InlineGhostTextView'; +import { ViewCollection } from './view/ViewCollection'; +import APIRegister from './APIRegister'; let client: LanguageClient; @@ -56,35 +59,67 @@ export function activate(context: vscode.ExtensionContext) { let verificationManager = new VerificationManager(client); let stateManager = new StateManager(client); - // Initialize UI Views - let gutterInfo = new GutterInformationView(verificationManager, context); - let statusBar = new StatusBarView(stateManager); + // // Initialize UI Views + let viewCollection = new ViewCollection(verificationManager, stateManager, context); - vscode.workspace.onDidSaveTextDocument(event => { - if (stateManager.getState() === State.Starting) { - return - } - const openEditor = vscode.window.visibleTextEditors.filter( - editor => editor.document.uri === event.uri - )[0] - stateManager.setState(State.Verifying); - console.log("Verification Started") - verificationManager.verify(openEditor, openEditor.document).then((_) => { - stateManager.setState(State.Finished) + APIRegister.register('onDidSaveTextDocument', (textDocument) => { + if (textDocument.languageId === "heyvl") { + if (stateManager.getState() === State.Starting) { + return + } + const openEditor = vscode.window.visibleTextEditors.filter( + editor => editor.document.uri === textDocument.uri + )[0] + stateManager.setState(State.Verifying); + console.log("Verification Started") + + verificationManager.verify(openEditor, textDocument).then((_) => { + stateManager.setState(State.Finished) + }) } - ) + }); + + + vscode.commands.registerCommand('caesar.restartServer', async () => { + console.log("Restarting Caesar...") + client.restart() + }); + + vscode.commands.registerCommand('caesar.startServer', async () => { + console.log("Starting Caesar...") + client.start() + }); + + vscode.commands.registerCommand('caesar.stopServer', async () => { + console.log("Stopping Caesar...") + client.stop() + }); + vscode.commands.registerCommand('caesar.verify', async () => { + const openEditor = vscode.window.activeTextEditor + if (openEditor) { + stateManager.setState(State.Verifying); + console.log("Verification Started") + verificationManager.verify(openEditor, openEditor.document).then((_) => { + stateManager.setState(State.Finished) + }) + } }); + + // Submit all received callbacks to vscode api + APIRegister.submitAll(); // Start the client. This will also launch the server client.start(); console.log('Caesar is now active!'); - context.subscriptions.push(statusBar); - context.subscriptions.push(gutterInfo); + + + // Add to a list of disposables which are disposed when this extension is deactivated. + context.subscriptions.push(viewCollection); context.subscriptions.push(client); } diff --git a/caesar-ext/src/Manager.ts b/caesar-ext/src/manager/Manager.ts similarity index 82% rename from caesar-ext/src/Manager.ts rename to caesar-ext/src/manager/Manager.ts index 0f0353b..2f81de8 100644 --- a/caesar-ext/src/Manager.ts +++ b/caesar-ext/src/manager/Manager.ts @@ -4,6 +4,7 @@ export class Manager { private observers: Observer[] = [] + /// Notify the observers with the latest verification status public notify(update: any) { this.observers.forEach(observer => observer.receiveUpdate(update)); @@ -37,6 +38,7 @@ export class Observer { private callback: (update: any) => void; private manager: Manager; + private enabled: boolean = true; public constructor(manager: Manager, callback: (update: any) => void) { this.callback = callback; @@ -45,9 +47,24 @@ export class Observer { this.manager.subscribe(this); } + public receiveUpdate(update: any): void { this.callback(update); } + + public disable() { + if (!this.enabled) { + return; + } + this.manager.unsubscribe(this); + } + + public enable() { + if (this.enabled) { + return; + } + this.manager.subscribe(this); + } } diff --git a/caesar-ext/src/StateManager.ts b/caesar-ext/src/manager/StateManager.ts similarity index 88% rename from caesar-ext/src/StateManager.ts rename to caesar-ext/src/manager/StateManager.ts index b34f296..2eacdfe 100644 --- a/caesar-ext/src/StateManager.ts +++ b/caesar-ext/src/manager/StateManager.ts @@ -18,11 +18,13 @@ export class StateManager extends Manager { private client: LanguageClient; - private state: State = State.Starting; + private state: State; constructor(client: LanguageClient) { super(); this.client = client; + this.state = State.Starting; + this.notify(this.state); client.onNotification("custom/serverReady", () => { this.setState(State.Ready); diff --git a/caesar-ext/src/VerificationManager.ts b/caesar-ext/src/manager/VerificationManager.ts similarity index 67% rename from caesar-ext/src/VerificationManager.ts rename to caesar-ext/src/manager/VerificationManager.ts index 7abceb2..9615367 100644 --- a/caesar-ext/src/VerificationManager.ts +++ b/caesar-ext/src/manager/VerificationManager.ts @@ -2,31 +2,33 @@ import * as vscode from "vscode"; import { LanguageClient } from "vscode-languageclient/node"; import { Manager, Observer } from "./Manager"; +import APIRegister from "../APIRegister"; export type VerificationStatus = Array<[vscode.Range, boolean]>; -// Subject export class VerificationManager extends Manager { private client: LanguageClient; + // private verificationStatus: Map = new Map(); private verificationStatus: VerificationStatus = []; - - constructor(client: LanguageClient) { super(); this.client = client; + } - public getStatus(): VerificationStatus { + public getStatus(editor: vscode.TextEditor): VerificationStatus { + // return this.verificationStatus.get(editor) || []; return this.verificationStatus; } - public setStatus(newStatus: VerificationStatus): void { + public setStatus(editor: vscode.TextEditor, newStatus: VerificationStatus): void { + // this.verificationStatus.set(editor, newStatus); this.verificationStatus = newStatus; - this.notify(newStatus); + this.notify(this.verificationStatus); } @@ -38,7 +40,7 @@ export class VerificationManager extends Manager { text: document.getText() } let response: VerificationStatus = await this.client.sendRequest('custom/verifyStatus', { text_document: documentItem }); - this.setStatus(response); + this.setStatus(editor, response); return response; } diff --git a/caesar-ext/src/utils.ts b/caesar-ext/src/utils.ts new file mode 100644 index 0000000..4a83a4c --- /dev/null +++ b/caesar-ext/src/utils.ts @@ -0,0 +1,19 @@ +import * as vscode from 'vscode'; + +const CONFIGURATION_SECTION = 'caesar'; + +export default class Configuration { + /// Get a configuration value from the configuration file with the given key + protected static getConfiguration(key: string): any { + const val: any | undefined = vscode.workspace.getConfiguration(CONFIGURATION_SECTION).get(key) + if (val === undefined) { + throw new Error(`${key} is not defined in the configuration file`); + } + return val; + } + + protected static getConfigurationPath(): string { + return "caesar." + } + +} diff --git a/caesar-ext/src/view/GutterInformationView.ts b/caesar-ext/src/view/GutterInformationView.ts new file mode 100644 index 0000000..6fc14a2 --- /dev/null +++ b/caesar-ext/src/view/GutterInformationView.ts @@ -0,0 +1,137 @@ + +import * as vscode from "vscode"; +import { VerificationManager, VerificationStatus } from "../manager/VerificationManager"; +import { Manager, Observer } from "../manager/Manager"; +import Configuration, { CONFIGURATION_SECTION, ConfigCategory, GutterInformationViewConfig } from "../Configuration"; +import APIRegister from "../APIRegister"; +import { EditorView } from "./View"; + + + +export enum VerifyStatus { + Verified, + Failed, + Unknown +} + +export enum VerificationColors { + Verified = '#66f542', + Failed = '#f23a3a', + Unknown = '#f7aa57' +} + + +/// The view that displays the verification status of individual (co)procedures in the gutter of the editor with corresponding icons +export class GutterInformationView extends EditorView { + private enabled: boolean; + private verificationObserver: Observer; + + private verifyDecType: vscode.TextEditorDecorationType; + private failedDecType: vscode.TextEditorDecorationType; + private unknownDecType: vscode.TextEditorDecorationType; + + private procStatus: VerificationStatus = []; + + constructor(verificationManager: VerificationManager, context: vscode.ExtensionContext) { + super(); + + this.enabled = GutterInformationViewConfig.get("showGutterIcons"); + + this.verifyDecType = vscode.window.createTextEditorDecorationType({ gutterIconSize: "contain", gutterIconPath: context.asAbsolutePath('images/verified.png') }); + this.failedDecType = vscode.window.createTextEditorDecorationType({ gutterIconSize: "contain", gutterIconPath: context.asAbsolutePath('images/failed.png') }); + this.unknownDecType = vscode.window.createTextEditorDecorationType({ gutterIconSize: "contain", gutterIconPath: context.asAbsolutePath('images/unknown.png') }); + + this.verificationObserver = new Observer(verificationManager, (update: VerificationStatus) => { this.receiveVerificationUpdate(update) }); + + // Register the configuration change listener + APIRegister.register("onDidChangeConfiguration", (e: vscode.ConfigurationChangeEvent) => { + if (e.affectsConfiguration(CONFIGURATION_SECTION)) { + console.log("Gutter Config Changed") + if (GutterInformationViewConfig.get("showGutterIcons")) { + this.enable(); + } else { + this.disable(); + } + } + }); + } + + /// Enable the GutterInformationView + public enable() { + if (this.enabled) { + return; + } + this.enabled = true; + this.verificationObserver.enable(); + this.updateView(vscode.window.activeTextEditor!) + } + + /// Disable the GutterInformationView + public disable() { + if (!this.enabled) { + return; + } + this.enabled = false; + this.verificationObserver.disable(); + this.clearVisibleEditors() + } + + /// Callback function for when the VerificationManager updates + private receiveVerificationUpdate(newStatus: VerificationStatus) { + // Update the decorations + const editor = vscode.window.activeTextEditor; + if (editor) { + this.procStatus = newStatus; + this.updateView(editor); + } + } + + + /// Clear the checkmarks from the given editor + public clearView(editor: vscode.TextEditor) { + editor.setDecorations(this.verifyDecType, []); + editor.setDecorations(this.failedDecType, []); + editor.setDecorations(this.unknownDecType, []); + } + + /// Update the checkmarks based on the latest verification status received from the VerificationManager + public updateView(editor: vscode.TextEditor) { + if (this.procStatus.length === 0 || !this.enabled) { + return; + } + const verifiedProcs: vscode.DecorationOptions[] = []; + const failedProcs: vscode.DecorationOptions[] = []; + const unknownProcs: vscode.DecorationOptions[] = []; + + for (const proc of this.procStatus) { + const verified = proc[1]; + + const line = proc[0].start.line; + const range = new vscode.Range(line, 0, line, 0); + if (verified) { + // Put the checkmark before the proc. + verifiedProcs.push({ range, hoverMessage: 'Verified' }); + } else { + // Put the X before the proc. + failedProcs.push({ range, hoverMessage: 'Not Verified' }); + } + } + editor.setDecorations(this.verifyDecType, verifiedProcs); + editor.setDecorations(this.failedDecType, failedProcs); + editor.setDecorations(this.unknownDecType, unknownProcs); + } + + + /// Dispose of the GutterInformationView + public dispose() { + this.clearVisibleEditors(); + this.verificationObserver.disable(); + this.verifyDecType.dispose(); + this.failedDecType.dispose(); + this.unknownDecType.dispose(); + } + +} + + + diff --git a/caesar-ext/src/view/InlineGhostTextView.ts b/caesar-ext/src/view/InlineGhostTextView.ts new file mode 100644 index 0000000..6f6b7fd --- /dev/null +++ b/caesar-ext/src/view/InlineGhostTextView.ts @@ -0,0 +1,99 @@ +import * as vscode from "vscode"; +import { Observer } from "../manager/Manager"; +import { VerificationManager, VerificationStatus } from "../manager/VerificationManager"; +import APIRegister from "../APIRegister"; +import { CONFIGURATION_SECTION, InlineGhostTextViewConfig } from "../Configuration"; +import { EditorView } from "./View"; + + +/// The view that shows the wp/wrt/ert of the respective lines as ghost text in the editor +export class InlineGhostTextView extends EditorView { + + private verificationObserver: Observer; + + + private lineTextMap: Map = new Map([[1, "test"], [2, "test2"], [3, "test3"]]); + + private decorationType: vscode.TextEditorDecorationType; + + constructor(verificationManager: VerificationManager) { + super(); + this.verificationObserver = new Observer(verificationManager, (update: VerificationStatus) => { this.receiveVerificationUpdate(update) }); + this.decorationType = vscode.window.createTextEditorDecorationType({}); + + + APIRegister.register("onDidChangeConfiguration", (e: vscode.ConfigurationChangeEvent) => { + if (e.affectsConfiguration(CONFIGURATION_SECTION)) { + if (InlineGhostTextViewConfig.get("showInlineGhostText")) { + this.enable(); + } else { + this.disable(); + } + } + }); + + } + + public enable() { + this.verificationObserver.enable(); + this.updateView(vscode.window.activeTextEditor!); + } + + public disable() { + this.verificationObserver.disable(); + this.clearVisibleEditors(); + } + + private receiveVerificationUpdate(newStatus: VerificationStatus) { + // Update the decorations + const editor = vscode.window.activeTextEditor; + if (editor) { + this.updateView(editor); + } + } + + public updateText(line: number, text: string) { + this.lineTextMap.set(line, text); + } + + public clearView(editor: vscode.TextEditor) { + editor.setDecorations(this.decorationType, []); + } + + public updateView(editor: vscode.TextEditor) { + const decorations: vscode.DecorationOptions[] = []; + + this.lineTextMap.forEach((text, line) => { + if (this.checkEmptyLine(Math.max(0, line - 1))) { + const range = new vscode.Range(Math.max(0, line - 1), 0, Math.max(0, line - 1), 0); + decorations.push({ + range, renderOptions: { + after: { + backgroundColor: new vscode.ThemeColor('caesar.inlineGhostBackgroundColor'), + color: new vscode.ThemeColor('caesar.inlineGhostForegroundColor'), + contentText: text + } + } + }); + } + }); + + editor.setDecorations(this.decorationType, decorations); + } + + public checkEmptyLine(line: number): boolean { + // Checks if the line above the given line number is empty + const textEditor = vscode.window.activeTextEditor; + if (textEditor && textEditor.document.lineCount > line) { + const lineText = textEditor.document.lineAt(line).text; + return lineText.trim() === ''; + } + return false; + } + + public dispose() { + this.clearVisibleEditors(); + this.decorationType.dispose(); + } + +} diff --git a/caesar-ext/src/view/StatusBarView.ts b/caesar-ext/src/view/StatusBarView.ts new file mode 100644 index 0000000..3b8d83f --- /dev/null +++ b/caesar-ext/src/view/StatusBarView.ts @@ -0,0 +1,111 @@ +import * as vscode from "vscode"; +import { VerificationStatus } from "../manager/VerificationManager"; +import { Manager, Observer } from "../manager/Manager"; +import { State, StateManager } from "../manager/StateManager"; +import APIRegister from "../APIRegister"; +import { CONFIGURATION_SECTION, StatusBarViewConfig } from "../Configuration"; + + + + + + +/// The view for the status bar at the bottom of the editor +export class StatusBarView { + + private stateObserver: Observer; + + private statusBarItems: Array; + private progressText: vscode.StatusBarItem; + + constructor(stateManager: StateManager) { + + this.stateObserver = new Observer(stateManager, (update: State) => { this.receiveStateUpdate(update) }); + + this.statusBarItems = []; + + this.progressText = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 99); + this.progressText.text = "caesar"; + + + this.progressText.tooltip = new vscode.MarkdownString( + "[Restart Caesar](command:caesar.restartServer)\n\n" + + "[Start Caesar](command:caesar.startServer)\n\n" + + "[Stop Caesar](command:caesar.stopServer)" + , true); + + this.statusBarItems.push(this.progressText); + + this.showStatusBar(); + + APIRegister.register("onDidChangeConfiguration", (e: vscode.ConfigurationChangeEvent) => { + if (e.affectsConfiguration(CONFIGURATION_SECTION)) { + if (StatusBarViewConfig.get("showStatusBar")) { + this.enable(); + } else { + this.disable(); + } + } + }); + + } + + private showStatusBar() { + for (const statusBarItem of this.statusBarItems) { + statusBarItem.show(); + } + } + + private hideStatusBar() { + for (const statusBarItem of this.statusBarItems) { + statusBarItem.hide(); + } + } + + /// Disable the status bar by hiding it and disabling the observer + public disable() { + this.hideStatusBar(); + this.stateObserver.disable(); + } + + /// Enable the status bar by showing it and enabling the observer + public enable() { + this.showStatusBar(); + this.stateObserver.enable(); + } + + /// Dispose of the status bar + public dispose() { + for (const statusBarItem of this.statusBarItems) { + statusBarItem.dispose(); + } + this.stateObserver.disable(); + } + + /// Update the status bar text based on the latest state received from the StateManager + private receiveStateUpdate(p: State) { + switch (p) { + case State.Starting: + this.progressText.text = StatusBarText.Starting; + break; + case State.Ready: + this.progressText.text = StatusBarText.Ready; + break; + case State.Verifying: + this.progressText.text = StatusBarText.Verifying; + break; + case State.Finished: + this.progressText.text = StatusBarText.Verified; + break; + } + } + +} + + +export enum StatusBarText { + Starting = "$(sync~spin) Starting Caesar...", + Ready = "$(check) Caesar Ready", + Verifying = "$(sync~spin) Verifying...", + Verified = "$(check) Verified" +} diff --git a/caesar-ext/src/view/View.ts b/caesar-ext/src/view/View.ts new file mode 100644 index 0000000..f0d2f7b --- /dev/null +++ b/caesar-ext/src/view/View.ts @@ -0,0 +1,18 @@ +import * as vscode from 'vscode'; + +export abstract class EditorView { + + + public abstract updateView(update: any): void; + + public abstract clearView(editor: vscode.TextEditor): void; + + public abstract dispose(): void; + + public clearVisibleEditors() { + const editors = vscode.window.visibleTextEditors; + editors.forEach(editor => this.clearView(editor)); + } + + +} diff --git a/caesar-ext/src/view/ViewCollection.ts b/caesar-ext/src/view/ViewCollection.ts new file mode 100644 index 0000000..54f77f6 --- /dev/null +++ b/caesar-ext/src/view/ViewCollection.ts @@ -0,0 +1,30 @@ +import * as vscode from "vscode"; + +import { StateManager } from "../manager/StateManager"; +import { VerificationManager } from "../manager/VerificationManager"; +import { GutterInformationView } from "./GutterInformationView"; +import { InlineGhostTextView } from "./InlineGhostTextView"; +import { StatusBarView } from "./StatusBarView"; + + +/// A container for all the views in the extension +/// Manages the creation and the on/off configurations of the views +export class ViewCollection { + public gutterInfo: GutterInformationView | null; + public statusBar: StatusBarView | null; + public inlineGhostText: InlineGhostTextView | null; + + + constructor(verificationManager: VerificationManager, stateManager: StateManager, context: vscode.ExtensionContext) { + this.gutterInfo = new GutterInformationView(verificationManager, context); + this.statusBar = new StatusBarView(stateManager); + this.inlineGhostText = new InlineGhostTextView(verificationManager); + } + + public dispose() { + this.gutterInfo?.dispose(); + this.statusBar?.dispose(); + this.inlineGhostText?.dispose(); + } + +} diff --git a/src/language_server/language_server.rs b/src/language_server/language_server.rs index f2f9298..4845c3d 100644 --- a/src/language_server/language_server.rs +++ b/src/language_server/language_server.rs @@ -45,7 +45,7 @@ pub fn run_server(options: &Options) -> Result<(), Box> let mut workspace_folders = Arc::new(Mutex::new(Vec::new())); let mut proc_status_map: HashMap> = HashMap::new(); - let start_notification = lsp_server::Notification::new("custom/serverReady".to_string(), {}); + let start_notification = lsp_server::Notification::new("custom/serverReady".to_string(), ()); let _ = connection .sender .send(Message::Notification(start_notification)); From 5c915371b2189d5a7588491d66366b574680d676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Schro=CC=88er?= Date: Wed, 8 May 2024 10:08:46 +0200 Subject: [PATCH 09/25] vscode-ext: overwrite with caesar-ext --- .gitignore | 2 +- caesar-ext/.vscode/launch.json | 21 - caesar-ext/.vscodeignore | 11 - caesar-ext/CHANGELOG.md | 9 - caesar-ext/README.md | 71 - caesar-ext/language-configuration.json | 30 - caesar-ext/package-lock.json | 3071 ---------------- caesar-ext/package.json | 125 - caesar-ext/src/extension.ts | 129 - caesar-ext/syntaxes/heyvl.tmLanguage.json | 93 - caesar-ext/vsc-extension-quickstart.md | 43 - {caesar-ext => vscode-ext}/.eslintrc.json | 0 {caesar-ext => vscode-ext}/.vscode-test.mjs | 0 .../.vscode/extensions.json | 0 vscode-ext/.vscode/launch.json | 28 +- .../.vscode/settings.json | 0 {caesar-ext => vscode-ext}/.vscode/tasks.json | 0 vscode-ext/.vscodeignore | 7 + vscode-ext/CHANGELOG.md | 2 +- vscode-ext/README.md | 71 +- {caesar-ext => vscode-ext}/images/failed.png | Bin {caesar-ext => vscode-ext}/images/unkown.png | Bin .../images/verified.png | Bin vscode-ext/package-lock.json | 3171 +++++++++++++++-- vscode-ext/package.json | 98 +- {caesar-ext => vscode-ext}/src/APIRegister.ts | 0 .../src/Configuration.ts | 0 vscode-ext/src/extension.ts | 133 +- .../src/manager/Manager.ts | 0 .../src/manager/StateManager.ts | 0 .../src/manager/VerificationManager.ts | 0 .../src/test/extension.test.ts | 0 {caesar-ext => vscode-ext}/src/utils.ts | 0 .../src/view/GutterInformationView.ts | 0 .../src/view/InlineGhostTextView.ts | 0 .../src/view/StatusBarView.ts | 0 {caesar-ext => vscode-ext}/src/view/View.ts | 0 .../src/view/ViewCollection.ts | 0 {caesar-ext => vscode-ext}/tsconfig.json | 0 vscode-ext/vsc-extension-quickstart.md | 38 +- 40 files changed, 3204 insertions(+), 3949 deletions(-) delete mode 100644 caesar-ext/.vscode/launch.json delete mode 100644 caesar-ext/.vscodeignore delete mode 100644 caesar-ext/CHANGELOG.md delete mode 100644 caesar-ext/README.md delete mode 100644 caesar-ext/language-configuration.json delete mode 100644 caesar-ext/package-lock.json delete mode 100644 caesar-ext/package.json delete mode 100644 caesar-ext/src/extension.ts delete mode 100644 caesar-ext/syntaxes/heyvl.tmLanguage.json delete mode 100644 caesar-ext/vsc-extension-quickstart.md rename {caesar-ext => vscode-ext}/.eslintrc.json (100%) rename {caesar-ext => vscode-ext}/.vscode-test.mjs (100%) rename {caesar-ext => vscode-ext}/.vscode/extensions.json (100%) rename {caesar-ext => vscode-ext}/.vscode/settings.json (100%) rename {caesar-ext => vscode-ext}/.vscode/tasks.json (100%) rename {caesar-ext => vscode-ext}/images/failed.png (100%) rename {caesar-ext => vscode-ext}/images/unkown.png (100%) rename {caesar-ext => vscode-ext}/images/verified.png (100%) rename {caesar-ext => vscode-ext}/src/APIRegister.ts (100%) rename {caesar-ext => vscode-ext}/src/Configuration.ts (100%) rename {caesar-ext => vscode-ext}/src/manager/Manager.ts (100%) rename {caesar-ext => vscode-ext}/src/manager/StateManager.ts (100%) rename {caesar-ext => vscode-ext}/src/manager/VerificationManager.ts (100%) rename {caesar-ext => vscode-ext}/src/test/extension.test.ts (100%) rename {caesar-ext => vscode-ext}/src/utils.ts (100%) rename {caesar-ext => vscode-ext}/src/view/GutterInformationView.ts (100%) rename {caesar-ext => vscode-ext}/src/view/InlineGhostTextView.ts (100%) rename {caesar-ext => vscode-ext}/src/view/StatusBarView.ts (100%) rename {caesar-ext => vscode-ext}/src/view/View.ts (100%) rename {caesar-ext => vscode-ext}/src/view/ViewCollection.ts (100%) rename {caesar-ext => vscode-ext}/tsconfig.json (100%) diff --git a/.gitignore b/.gitignore index afbddd5..59414f4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ target .DS_Store benchmark-results.csv vscode-ext/node_modules/ -caesar-ext/out/ +vscode-ext/out/ node_modules/ # .dockerignore is symlinked to the .gitignore, so this line is useful: .git diff --git a/caesar-ext/.vscode/launch.json b/caesar-ext/.vscode/launch.json deleted file mode 100644 index 8880465..0000000 --- a/caesar-ext/.vscode/launch.json +++ /dev/null @@ -1,21 +0,0 @@ -// A launch configuration that compiles the extension and then opens it inside a new window -// Use IntelliSense to learn about possible attributes. -// Hover to view descriptions of existing attributes. -// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Run Extension", - "type": "extensionHost", - "request": "launch", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}" - ], - "outFiles": [ - "${workspaceFolder}/out/**/*.js" - ], - "preLaunchTask": "${defaultBuildTask}" - } - ] -} diff --git a/caesar-ext/.vscodeignore b/caesar-ext/.vscodeignore deleted file mode 100644 index 72aa0fe..0000000 --- a/caesar-ext/.vscodeignore +++ /dev/null @@ -1,11 +0,0 @@ -.vscode/** -.vscode-test/** -src/** -.gitignore -.yarnrc -vsc-extension-quickstart.md -**/tsconfig.json -**/.eslintrc.json -**/*.map -**/*.ts -**/.vscode-test.* diff --git a/caesar-ext/CHANGELOG.md b/caesar-ext/CHANGELOG.md deleted file mode 100644 index 0421b91..0000000 --- a/caesar-ext/CHANGELOG.md +++ /dev/null @@ -1,9 +0,0 @@ -# Change Log - -All notable changes to the "caesar" extension will be documented in this file. - -Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. - -## [Unreleased] - -- Initial release \ No newline at end of file diff --git a/caesar-ext/README.md b/caesar-ext/README.md deleted file mode 100644 index 61adf17..0000000 --- a/caesar-ext/README.md +++ /dev/null @@ -1,71 +0,0 @@ -# caesar README - -This is the README for your extension "caesar". After writing up a brief description, we recommend including the following sections. - -## Features - -Describe specific features of your extension including screenshots of your extension in action. Image paths are relative to this README file. - -For example if there is an image subfolder under your extension project workspace: - -\!\[feature X\]\(images/feature-x.png\) - -> Tip: Many popular extensions utilize animations. This is an excellent way to show off your extension! We recommend short, focused animations that are easy to follow. - -## Requirements - -If you have any requirements or dependencies, add a section describing those and how to install and configure them. - -## Extension Settings - -Include if your extension adds any VS Code settings through the `contributes.configuration` extension point. - -For example: - -This extension contributes the following settings: - -* `myExtension.enable`: Enable/disable this extension. -* `myExtension.thing`: Set to `blah` to do something. - -## Known Issues - -Calling out known issues can help limit users opening duplicate issues against your extension. - -## Release Notes - -Users appreciate release notes as you update your extension. - -### 1.0.0 - -Initial release of ... - -### 1.0.1 - -Fixed issue #. - -### 1.1.0 - -Added features X, Y, and Z. - ---- - -## Following extension guidelines - -Ensure that you've read through the extensions guidelines and follow the best practices for creating your extension. - -* [Extension Guidelines](https://code.visualstudio.com/api/references/extension-guidelines) - -## Working with Markdown - -You can author your README using Visual Studio Code. Here are some useful editor keyboard shortcuts: - -* Split the editor (`Cmd+\` on macOS or `Ctrl+\` on Windows and Linux). -* Toggle preview (`Shift+Cmd+V` on macOS or `Shift+Ctrl+V` on Windows and Linux). -* Press `Ctrl+Space` (Windows, Linux, macOS) to see a list of Markdown snippets. - -## For more information - -* [Visual Studio Code's Markdown Support](http://code.visualstudio.com/docs/languages/markdown) -* [Markdown Syntax Reference](https://help.github.com/articles/markdown-basics/) - -**Enjoy!** diff --git a/caesar-ext/language-configuration.json b/caesar-ext/language-configuration.json deleted file mode 100644 index 5984db8..0000000 --- a/caesar-ext/language-configuration.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "comments": { - // symbol used for single line comment. - "lineComment": "//", - // symbols used for start and end a block comment. - "blockComment": [ "/*", "*/" ] - }, - // symbols used as brackets - "brackets": [ - ["{", "}"], - ["[", "]"], - ["(", ")"] - ], - // symbols that are auto closed when typing - "autoClosingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["\"", "\""], - ["'", "'"] - ], - // symbols that can be used to surround a selection - "surroundingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["\"", "\""], - ["'", "'"] - ] -} \ No newline at end of file diff --git a/caesar-ext/package-lock.json b/caesar-ext/package-lock.json deleted file mode 100644 index 19925dd..0000000 --- a/caesar-ext/package-lock.json +++ /dev/null @@ -1,3071 +0,0 @@ -{ - "name": "caesar", - "version": "0.0.1", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "caesar", - "version": "0.0.1", - "dependencies": { - "vscode-languageclient": "9.0.1" - }, - "devDependencies": { - "@types/mocha": "^10.0.6", - "@types/node": "18.x", - "@types/vscode": "^1.87.0", - "@typescript-eslint/eslint-plugin": "^7.0.2", - "@typescript-eslint/parser": "^7.0.2", - "@vscode/test-cli": "^0.0.6", - "@vscode/test-electron": "^2.3.9", - "eslint": "^8.56.0", - "typescript": "^5.3.3" - }, - "engines": { - "vscode": "^1.87.0" - } - }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", - "dev": true - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "node_modules/@types/mocha": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", - "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", - "dev": true - }, - "node_modules/@types/node": { - "version": "18.19.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.21.tgz", - "integrity": "sha512-2Q2NeB6BmiTFQi4DHBzncSoq/cJMLDdhPaAoJFnFCyD9a8VPZRf7a1GAwp1Edb7ROaZc5Jz/tnZyL6EsWMRaqw==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true - }, - "node_modules/@types/vscode": { - "version": "1.87.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.87.0.tgz", - "integrity": "sha512-y3yYJV2esWr8LNjp3VNbSMWG7Y43jC8pCldG8YwiHGAQbsymkkMMt0aDT1xZIOFM2eFcNiUc+dJMx1+Z0UT8fg==", - "dev": true - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.1.tgz", - "integrity": "sha512-zioDz623d0RHNhvx0eesUmGfIjzrk18nSBC8xewepKXbBvN/7c1qImV7Hg8TI1URTxKax7/zxfxj3Uph8Chcuw==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/type-utils": "7.1.1", - "@typescript-eslint/utils": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.4", - "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.1.tgz", - "integrity": "sha512-ZWUFyL0z04R1nAEgr9e79YtV5LbafdOtN7yapNbn1ansMyaegl2D4bL7vHoJ4HPSc4CaLwuCVas8CVuneKzplQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/typescript-estree": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", - "debug": "^4.3.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", - "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.1.tgz", - "integrity": "sha512-5r4RKze6XHEEhlZnJtR3GYeCh1IueUHdbrukV2KSlLXaTjuSfeVF8mZUVPLovidCuZfbVjfhi4c0DNSa/Rdg5g==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "7.1.1", - "@typescript-eslint/utils": "7.1.1", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", - "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", - "dev": true, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", - "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.1.tgz", - "integrity": "sha512-thOXM89xA03xAE0lW7alstvnyoBUbBX38YtY+zAUcpRPcq9EIhXPuJ0YTv948MbzmKh6e1AUszn5cBFK49Umqg==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/typescript-estree": "7.1.1", - "semver": "^7.5.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", - "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.1.1", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "node_modules/@vscode/test-cli": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@vscode/test-cli/-/test-cli-0.0.6.tgz", - "integrity": "sha512-4i61OUv5PQr3GxhHOuUgHdgBDfIO/kXTPCsEyFiMaY4SOqQTgkTmyZLagHehjOgCfsXdcrJa3zgQ7zoc+Dh6hQ==", - "dev": true, - "dependencies": { - "@types/mocha": "^10.0.2", - "c8": "^9.1.0", - "chokidar": "^3.5.3", - "enhanced-resolve": "^5.15.0", - "glob": "^10.3.10", - "minimatch": "^9.0.3", - "mocha": "^10.2.0", - "supports-color": "^9.4.0", - "yargs": "^17.7.2" - }, - "bin": { - "vscode-test": "out/bin.mjs" - } - }, - "node_modules/@vscode/test-electron": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.9.tgz", - "integrity": "sha512-z3eiChaCQXMqBnk2aHHSEkobmC2VRalFQN0ApOAtydL172zXGxTwGrRtviT5HnUB+Q+G3vtEYFtuQkYqBzYgMA==", - "dev": true, - "dependencies": { - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "jszip": "^3.10.1", - "semver": "^7.5.2" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/c8": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/c8/-/c8-9.1.0.tgz", - "integrity": "sha512-mBWcT5iqNir1zIkzSPyI3NCR9EZCVI3WUD+AVO17MVWTSFNyUueXE82qTeampNtTr+ilN/5Ua3j24LgbCKjDVg==", - "dev": true, - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@istanbuljs/schema": "^0.1.3", - "find-up": "^5.0.0", - "foreground-child": "^3.1.1", - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-report": "^3.0.1", - "istanbul-reports": "^3.1.6", - "test-exclude": "^6.0.0", - "v8-to-istanbul": "^9.0.0", - "yargs": "^17.7.2", - "yargs-parser": "^21.1.1" - }, - "bin": { - "c8": "bin/c8.js" - }, - "engines": { - "node": ">=14.14.0" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/enhanced-resolve": { - "version": "5.15.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.1.tgz", - "integrity": "sha512-3d3JRbwsCLJsYgvb6NuWEG44jjPSOMuS73L/6+7BZuoKm3W+qXnSoIYVHi8dG7Qcg4inAY4jbzkZ7MnskePeDg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true - }, - "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", - "dev": true - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dev": true, - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/jszip": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", - "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", - "dev": true, - "dependencies": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "setimmediate": "^1.0.5" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lie": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", - "dev": true, - "dependencies": { - "immediate": "~3.0.5" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } - }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/mocha": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.3.0.tgz", - "integrity": "sha512-uF2XJs+7xSLsrmIvn37i/wnc91nw7XjOQB8ccyx5aEgdnohr7n+rEiZP23WkCYHjilR6+EboEnbq/ZQDz4LSbg==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "8.1.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/mocha/node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/mocha/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/mocha/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/mocha/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/mocha/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", - "dev": true, - "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", - "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/ts-api-utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", - "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", - "dev": true, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/v8-to-istanbul": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", - "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/vscode-jsonrpc": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", - "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/vscode-languageclient": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", - "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", - "dependencies": { - "minimatch": "^5.1.0", - "semver": "^7.3.7", - "vscode-languageserver-protocol": "3.17.5" - }, - "engines": { - "vscode": "^1.82.0" - } - }, - "node_modules/vscode-languageclient/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/vscode-languageserver-protocol": { - "version": "3.17.5", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", - "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", - "dependencies": { - "vscode-jsonrpc": "8.2.0", - "vscode-languageserver-types": "3.17.5" - } - }, - "node_modules/vscode-languageserver-types": { - "version": "3.17.5", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", - "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/caesar-ext/package.json b/caesar-ext/package.json deleted file mode 100644 index 8f31983..0000000 --- a/caesar-ext/package.json +++ /dev/null @@ -1,125 +0,0 @@ -{ - "name": "caesar", - "displayName": "caesar", - "description": "VSCode Extension of the Deductive Probabilistic Program Verifier Caesar", - "version": "0.0.1", - "engines": { - "vscode": "^1.87.0" - }, - "categories": [ - "Other" - ], - "main": "./out/extension.js", - "contributes": { - "commands": [ - { - "command": "caesar.restartServer", - "title": "Caesar: Restart Server" - }, - { - "command": "caesar.startServer", - "title": "Caesar: Start Server" - }, - { - "command": "caesar.stopServer", - "title": "Caesar: Stop Server" - }, - { - "command": "caesar.verify", - "title": "Caesar: Verify" - } - ], - "languages": [ - { - "id": "heyvl", - "aliases": [ - "HeyVL", - "heyvl" - ], - "extensions": [ - ".heyvl" - ], - "configuration": "./language-configuration.json" - } - ], - "grammars": [ - { - "language": "heyvl", - "scopeName": "source.heyvl", - "path": "./syntaxes/heyvl.tmLanguage.json" - } - ], - "configuration": { - "type": "object", - "title": "Caesar", - "properties": { - "caesar.uI.gutterIcons.showGutterIcons": { - "type": "boolean", - "default": true, - "description": "Specifies whether to show icons on the gutter about the verification status." - }, - "caesar.uI.inlineGhostText.showInlineGhostText": { - "type": "boolean", - "default": true, - "description": "Specifies whether to show inline ghost text about the wp/wlp/ert." - }, - "caesar.uI.statusBar.showStatusBar": { - "type": "boolean", - "default": true, - "description": "Specifies whether to show the status bar." - }, - "caesar.automaticVerification": { - "type": "string", - "default": "onsave", - "enum": [ - "never", - "onsave" - ], - "description": "Specifies when Caesar automatically verifies the file." - } - } - }, - "colors": [ - { - "id": "caesar.inlineGhostBackgroundColor", - "description": "Specifies the background color of the inline ghost texts ", - "defaults": { - "dark": "#00000000", - "light": "#00000000", - "highContrast": "#00000000" - } - }, - { - "id": "caesar.inlineGhostForegroundColor", - "description": "Specifies the foreground color of the inline ghost texts", - "defaults": { - "dark": "#99999959", - "light": "#99999959", - "highContrast": "#99999999" - } - } - ] - }, - "scripts": { - "vscode:prepublish": "npm run compile", - "compile": "tsc -p ./", - "watch": "tsc -watch -p ./", - "pretest": "npm run compile && npm run lint", - "lint": "eslint src --ext ts", - "test": "vscode-test" - }, - "devDependencies": { - "@types/vscode": "^1.87.0", - "@types/mocha": "^10.0.6", - "@types/node": "18.x", - "@typescript-eslint/eslint-plugin": "^7.0.2", - "@typescript-eslint/parser": "^7.0.2", - "eslint": "^8.56.0", - "typescript": "^5.3.3", - "@vscode/test-cli": "^0.0.6", - "@vscode/test-electron": "^2.3.9" - }, - "dependencies": { - "vscode-languageclient": "9.0.1" - } -} diff --git a/caesar-ext/src/extension.ts b/caesar-ext/src/extension.ts deleted file mode 100644 index a3e4717..0000000 --- a/caesar-ext/src/extension.ts +++ /dev/null @@ -1,129 +0,0 @@ -// The module 'vscode' contains the VS Code extensibility API -// Import the module and reference it with the alias vscode in your code below -import * as vscode from 'vscode'; -import * as path from 'path'; -import * as os from 'os'; -import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient/node'; -import { VerificationManager } from './manager/VerificationManager'; -import { GutterInformationView } from './view/GutterInformationView'; -import { StatusBarView } from './view/StatusBarView'; -import { State, StateManager } from './manager/StateManager'; -import { InlineGhostTextView } from './view/InlineGhostTextView'; -import { ViewCollection } from './view/ViewCollection'; -import APIRegister from './APIRegister'; - - -let client: LanguageClient; -// This method is called when your extension is activated -// Your extension is activated the very first time the command is executed -export function activate(context: vscode.ExtensionContext) { - - let serverExecutable = "cargo" - - // If the extension is launched in debug mode then the debug server options are used - // Otherwise the run options are used - let serverOptions: ServerOptions = { - run: { - command: serverExecutable, - args: ['run', '--', '--language-server'], - options: { cwd: path.resolve(os.homedir(), 'caesar') }, - }, - debug: { - command: serverExecutable, - args: ['run', '--', '--language-server'], - options: { cwd: path.resolve(os.homedir(), 'caesar') }, - } - }; - - // Options to control the language client - let clientOptions: LanguageClientOptions = { - diagnosticCollectionName: 'caesar', - // Register the server for heyvl documents - documentSelector: [{ scheme: 'file', language: 'heyvl' }], - synchronize: { - // Notify the server about file changes to '.clientrc files contained in the workspace - fileEvents: vscode.workspace.createFileSystemWatcher('**/*.heyvl') - } - }; - - // Create the language client and start the client. - client = new LanguageClient( - 'caesar', - 'Caesar', - serverOptions, - clientOptions - ); - - - // Initialize Managers - let verificationManager = new VerificationManager(client); - let stateManager = new StateManager(client); - - // // Initialize UI Views - let viewCollection = new ViewCollection(verificationManager, stateManager, context); - - - APIRegister.register('onDidSaveTextDocument', (textDocument) => { - if (textDocument.languageId === "heyvl") { - if (stateManager.getState() === State.Starting) { - return - } - const openEditor = vscode.window.visibleTextEditors.filter( - editor => editor.document.uri === textDocument.uri - )[0] - stateManager.setState(State.Verifying); - console.log("Verification Started") - - verificationManager.verify(openEditor, textDocument).then((_) => { - stateManager.setState(State.Finished) - }) - } - }); - - - vscode.commands.registerCommand('caesar.restartServer', async () => { - console.log("Restarting Caesar...") - client.restart() - }); - - vscode.commands.registerCommand('caesar.startServer', async () => { - console.log("Starting Caesar...") - client.start() - - }); - - vscode.commands.registerCommand('caesar.stopServer', async () => { - console.log("Stopping Caesar...") - client.stop() - }); - - vscode.commands.registerCommand('caesar.verify', async () => { - const openEditor = vscode.window.activeTextEditor - if (openEditor) { - stateManager.setState(State.Verifying); - console.log("Verification Started") - verificationManager.verify(openEditor, openEditor.document).then((_) => { - stateManager.setState(State.Finished) - }) - } - }); - - - // Submit all received callbacks to vscode api - APIRegister.submitAll(); - // Start the client. This will also launch the server - client.start(); - - console.log('Caesar is now active!'); - - - - // Add to a list of disposables which are disposed when this extension is deactivated. - context.subscriptions.push(viewCollection); - context.subscriptions.push(client); - -} - -// This method is called when the extension is deactivated -export function deactivate() { } - diff --git a/caesar-ext/syntaxes/heyvl.tmLanguage.json b/caesar-ext/syntaxes/heyvl.tmLanguage.json deleted file mode 100644 index a12d646..0000000 --- a/caesar-ext/syntaxes/heyvl.tmLanguage.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", - "name": "HeyVL", - "patterns": [ - { - "include": "#keywords" - }, - { - "include": "#strings" - }, - { - "include": "#comments" - }, - { - "include": "#type" - }, - { - "include": "#constant" - } - ], - "repository": { - "keywords": { - "patterns": [ - { - "name": "keyword.control.heyvl", - "match": "\\b(var|(co)?assume|(co)?assert|(co)?negate|(co)?validate|if|else|(co)?proc|pre|post|(co)?compare|tick|reward|while|(co)?havoc|domain|func|axiom)\\b" - }, - { - "name": "keyword.operator.heyvl", - "match": "\\b(forall|exists|inf|sup|ite|let)\\b" - } - ] - }, - "type": { - "patterns": [ - { - "name": "entity.name.type", - "match": "(\\[\\])+[a-zA-Z]+\\b" - }, - { - "name": "entity.name.type", - "match": "\\b(Bool|Int|UInt|Real|UReal|EUReal)\\b" - } - ] - }, - "paren-expr": { - "begin": "\\(", - "end": "\\)", - "beginCaptures": { - "0": { - "name": "punctuation.paren.open" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.paren.close" - } - }, - "name": "expression.group", - "patterns": [ - { - "include": "#expr" - } - ] - }, - "comments": { - "patterns": [ - { - "match": "/{2}.*", - "name": "comment.single.heyvl" - }, - { - "begin": "/\\*", - "end": "\\*/", - "name": "comment.block.heyvl" - } - ] - }, - "constant": { - "patterns": [ - { - "name": "constant.numeric.heyvl", - "match": "\\b[0-9]+(\\.[0-9]+)?\\b" - }, - { - "name": "constant.language.heyvl", - "match": "\\b(true|false|∞|\\\\[a-zA-Z]+)\\b" - } - ] - } - }, - "scopeName": "source.heyvl" -} diff --git a/caesar-ext/vsc-extension-quickstart.md b/caesar-ext/vsc-extension-quickstart.md deleted file mode 100644 index 3d8ce06..0000000 --- a/caesar-ext/vsc-extension-quickstart.md +++ /dev/null @@ -1,43 +0,0 @@ -# Welcome to your VS Code Extension - -## What's in the folder - -* This folder contains all of the files necessary for your extension. -* `package.json` - this is the manifest file in which you declare your extension and command. - * The sample plugin registers a command and defines its title and command name. With this information VS Code can show the command in the command palette. It doesn’t yet need to load the plugin. -* `src/extension.ts` - this is the main file where you will provide the implementation of your command. - * The file exports one function, `activate`, which is called the very first time your extension is activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`. - * We pass the function containing the implementation of the command as the second parameter to `registerCommand`. - -## Get up and running straight away - -* Press `F5` to open a new window with your extension loaded. -* Run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`. -* Set breakpoints in your code inside `src/extension.ts` to debug your extension. -* Find output from your extension in the debug console. - -## Make changes - -* You can relaunch the extension from the debug toolbar after changing code in `src/extension.ts`. -* You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes. - -## Explore the API - -* You can open the full set of our API when you open the file `node_modules/@types/vscode/index.d.ts`. - -## Run tests - -* Install the [Extension Test Runner](https://marketplace.visualstudio.com/items?itemName=ms-vscode.extension-test-runner) -* Run the "watch" task via the **Tasks: Run Task** command. Make sure this is running, or tests might not be discovered. -* Open the Testing view from the activity bar and click the Run Test" button, or use the hotkey `Ctrl/Cmd + ; A` -* See the output of the test result in the Test Results view. -* Make changes to `src/test/extension.test.ts` or create new test files inside the `test` folder. - * The provided test runner will only consider files matching the name pattern `**.test.ts`. - * You can create folders inside the `test` folder to structure your tests any way you want. - -## Go further - -* [Follow UX guidelines](https://code.visualstudio.com/api/ux-guidelines/overview) to create extensions that seamlessly integrate with VS Code's native interface and patterns. - * Reduce the extension size and improve the startup time by [bundling your extension](https://code.visualstudio.com/api/working-with-extensions/bundling-extension). - * [Publish your extension](https://code.visualstudio.com/api/working-with-extensions/publishing-extension) on the VS Code extension marketplace. - * Automate builds by setting up [Continuous Integration](https://code.visualstudio.com/api/working-with-extensions/continuous-integration). diff --git a/caesar-ext/.eslintrc.json b/vscode-ext/.eslintrc.json similarity index 100% rename from caesar-ext/.eslintrc.json rename to vscode-ext/.eslintrc.json diff --git a/caesar-ext/.vscode-test.mjs b/vscode-ext/.vscode-test.mjs similarity index 100% rename from caesar-ext/.vscode-test.mjs rename to vscode-ext/.vscode-test.mjs diff --git a/caesar-ext/.vscode/extensions.json b/vscode-ext/.vscode/extensions.json similarity index 100% rename from caesar-ext/.vscode/extensions.json rename to vscode-ext/.vscode/extensions.json diff --git a/vscode-ext/.vscode/launch.json b/vscode-ext/.vscode/launch.json index 0e191b5..8880465 100644 --- a/vscode-ext/.vscode/launch.json +++ b/vscode-ext/.vscode/launch.json @@ -1,17 +1,21 @@ -// A launch configuration that launches the extension inside a new window +// A launch configuration that compiles the extension and then opens it inside a new window // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 { "version": "0.2.0", - "configurations": [ - { - "name": "Extension", - "type": "extensionHost", - "request": "launch", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}" - ] - } - ] -} \ No newline at end of file + "configurations": [ + { + "name": "Run Extension", + "type": "extensionHost", + "request": "launch", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}" + ], + "outFiles": [ + "${workspaceFolder}/out/**/*.js" + ], + "preLaunchTask": "${defaultBuildTask}" + } + ] +} diff --git a/caesar-ext/.vscode/settings.json b/vscode-ext/.vscode/settings.json similarity index 100% rename from caesar-ext/.vscode/settings.json rename to vscode-ext/.vscode/settings.json diff --git a/caesar-ext/.vscode/tasks.json b/vscode-ext/.vscode/tasks.json similarity index 100% rename from caesar-ext/.vscode/tasks.json rename to vscode-ext/.vscode/tasks.json diff --git a/vscode-ext/.vscodeignore b/vscode-ext/.vscodeignore index f369b5e..72aa0fe 100644 --- a/vscode-ext/.vscodeignore +++ b/vscode-ext/.vscodeignore @@ -1,4 +1,11 @@ .vscode/** .vscode-test/** +src/** .gitignore +.yarnrc vsc-extension-quickstart.md +**/tsconfig.json +**/.eslintrc.json +**/*.map +**/*.ts +**/.vscode-test.* diff --git a/vscode-ext/CHANGELOG.md b/vscode-ext/CHANGELOG.md index b1faa88..0421b91 100644 --- a/vscode-ext/CHANGELOG.md +++ b/vscode-ext/CHANGELOG.md @@ -1,6 +1,6 @@ # Change Log -All notable changes to the "heyvl" extension will be documented in this file. +All notable changes to the "caesar" extension will be documented in this file. Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. diff --git a/vscode-ext/README.md b/vscode-ext/README.md index 7eeb234..61adf17 100644 --- a/vscode-ext/README.md +++ b/vscode-ext/README.md @@ -1,14 +1,71 @@ -# HeyVL Language Extension +# caesar README -This extension can be installed locally on MacOS/Linux via -```bash -ln -s $PWD ~/.vscode/extensions/heyvl -``` +This is the README for your extension "caesar". After writing up a brief description, we recommend including the following sections. -See [the VSCode docs](https://vscode-docs.readthedocs.io/en/stable/extensions/install-extension/) for more information. +## Features + +Describe specific features of your extension including screenshots of your extension in action. Image paths are relative to this README file. + +For example if there is an image subfolder under your extension project workspace: + +\!\[feature X\]\(images/feature-x.png\) + +> Tip: Many popular extensions utilize animations. This is an excellent way to show off your extension! We recommend short, focused animations that are easy to follow. + +## Requirements + +If you have any requirements or dependencies, add a section describing those and how to install and configure them. + +## Extension Settings + +Include if your extension adds any VS Code settings through the `contributes.configuration` extension point. + +For example: + +This extension contributes the following settings: + +* `myExtension.enable`: Enable/disable this extension. +* `myExtension.thing`: Set to `blah` to do something. + +## Known Issues + +Calling out known issues can help limit users opening duplicate issues against your extension. ## Release Notes +Users appreciate release notes as you update your extension. + ### 1.0.0 -Initial release. +Initial release of ... + +### 1.0.1 + +Fixed issue #. + +### 1.1.0 + +Added features X, Y, and Z. + +--- + +## Following extension guidelines + +Ensure that you've read through the extensions guidelines and follow the best practices for creating your extension. + +* [Extension Guidelines](https://code.visualstudio.com/api/references/extension-guidelines) + +## Working with Markdown + +You can author your README using Visual Studio Code. Here are some useful editor keyboard shortcuts: + +* Split the editor (`Cmd+\` on macOS or `Ctrl+\` on Windows and Linux). +* Toggle preview (`Shift+Cmd+V` on macOS or `Shift+Ctrl+V` on Windows and Linux). +* Press `Ctrl+Space` (Windows, Linux, macOS) to see a list of Markdown snippets. + +## For more information + +* [Visual Studio Code's Markdown Support](http://code.visualstudio.com/docs/languages/markdown) +* [Markdown Syntax Reference](https://help.github.com/articles/markdown-basics/) + +**Enjoy!** diff --git a/caesar-ext/images/failed.png b/vscode-ext/images/failed.png similarity index 100% rename from caesar-ext/images/failed.png rename to vscode-ext/images/failed.png diff --git a/caesar-ext/images/unkown.png b/vscode-ext/images/unkown.png similarity index 100% rename from caesar-ext/images/unkown.png rename to vscode-ext/images/unkown.png diff --git a/caesar-ext/images/verified.png b/vscode-ext/images/verified.png similarity index 100% rename from caesar-ext/images/verified.png rename to vscode-ext/images/verified.png diff --git a/vscode-ext/package-lock.json b/vscode-ext/package-lock.json index 6ad640b..19925dd 100644 --- a/vscode-ext/package-lock.json +++ b/vscode-ext/package-lock.json @@ -1,204 +1,2684 @@ { - "name": "heyvl", + "name": "caesar", "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "heyvl", + "name": "caesar", "version": "0.0.1", + "dependencies": { + "vscode-languageclient": "9.0.1" + }, "devDependencies": { - "@types/node": "^8.10.25", - "@types/vscode": "^1.71.0", - "tslint": "^5.16.0", - "typescript": "^3.4.5" + "@types/mocha": "^10.0.6", + "@types/node": "18.x", + "@types/vscode": "^1.87.0", + "@typescript-eslint/eslint-plugin": "^7.0.2", + "@typescript-eslint/parser": "^7.0.2", + "@vscode/test-cli": "^0.0.6", + "@vscode/test-electron": "^2.3.9", + "eslint": "^8.56.0", + "typescript": "^5.3.3" + }, + "engines": { + "vscode": "^1.87.0" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/mocha": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", + "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.19.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.21.tgz", + "integrity": "sha512-2Q2NeB6BmiTFQi4DHBzncSoq/cJMLDdhPaAoJFnFCyD9a8VPZRf7a1GAwp1Edb7ROaZc5Jz/tnZyL6EsWMRaqw==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true + }, + "node_modules/@types/vscode": { + "version": "1.87.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.87.0.tgz", + "integrity": "sha512-y3yYJV2esWr8LNjp3VNbSMWG7Y43jC8pCldG8YwiHGAQbsymkkMMt0aDT1xZIOFM2eFcNiUc+dJMx1+Z0UT8fg==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.1.tgz", + "integrity": "sha512-zioDz623d0RHNhvx0eesUmGfIjzrk18nSBC8xewepKXbBvN/7c1qImV7Hg8TI1URTxKax7/zxfxj3Uph8Chcuw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/type-utils": "7.1.1", + "@typescript-eslint/utils": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.1.tgz", + "integrity": "sha512-ZWUFyL0z04R1nAEgr9e79YtV5LbafdOtN7yapNbn1ansMyaegl2D4bL7vHoJ4HPSc4CaLwuCVas8CVuneKzplQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/typescript-estree": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", + "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.1.tgz", + "integrity": "sha512-5r4RKze6XHEEhlZnJtR3GYeCh1IueUHdbrukV2KSlLXaTjuSfeVF8mZUVPLovidCuZfbVjfhi4c0DNSa/Rdg5g==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.1.1", + "@typescript-eslint/utils": "7.1.1", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", + "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", + "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/visitor-keys": "7.1.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.1.tgz", + "integrity": "sha512-thOXM89xA03xAE0lW7alstvnyoBUbBX38YtY+zAUcpRPcq9EIhXPuJ0YTv948MbzmKh6e1AUszn5cBFK49Umqg==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "7.1.1", + "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/typescript-estree": "7.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", + "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.1.1", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@vscode/test-cli": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@vscode/test-cli/-/test-cli-0.0.6.tgz", + "integrity": "sha512-4i61OUv5PQr3GxhHOuUgHdgBDfIO/kXTPCsEyFiMaY4SOqQTgkTmyZLagHehjOgCfsXdcrJa3zgQ7zoc+Dh6hQ==", + "dev": true, + "dependencies": { + "@types/mocha": "^10.0.2", + "c8": "^9.1.0", + "chokidar": "^3.5.3", + "enhanced-resolve": "^5.15.0", + "glob": "^10.3.10", + "minimatch": "^9.0.3", + "mocha": "^10.2.0", + "supports-color": "^9.4.0", + "yargs": "^17.7.2" + }, + "bin": { + "vscode-test": "out/bin.mjs" + } + }, + "node_modules/@vscode/test-electron": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.9.tgz", + "integrity": "sha512-z3eiChaCQXMqBnk2aHHSEkobmC2VRalFQN0ApOAtydL172zXGxTwGrRtviT5HnUB+Q+G3vtEYFtuQkYqBzYgMA==", + "dev": true, + "dependencies": { + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "jszip": "^3.10.1", + "semver": "^7.5.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/c8": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/c8/-/c8-9.1.0.tgz", + "integrity": "sha512-mBWcT5iqNir1zIkzSPyI3NCR9EZCVI3WUD+AVO17MVWTSFNyUueXE82qTeampNtTr+ilN/5Ua3j24LgbCKjDVg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@istanbuljs/schema": "^0.1.3", + "find-up": "^5.0.0", + "foreground-child": "^3.1.1", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.1.6", + "test-exclude": "^6.0.0", + "v8-to-istanbul": "^9.0.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1" + }, + "bin": { + "c8": "bin/c8.js" + }, + "engines": { + "node": ">=14.14.0" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/enhanced-resolve": { + "version": "5.15.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.1.tgz", + "integrity": "sha512-3d3JRbwsCLJsYgvb6NuWEG44jjPSOMuS73L/6+7BZuoKm3W+qXnSoIYVHi8dG7Qcg4inAY4jbzkZ7MnskePeDg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dev": true, + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mocha": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.3.0.tgz", + "integrity": "sha512-uF2XJs+7xSLsrmIvn37i/wnc91nw7XjOQB8ccyx5aEgdnohr7n+rEiZP23WkCYHjilR6+EboEnbq/ZQDz4LSbg==", + "dev": true, + "dependencies": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "8.1.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/mocha/node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/mocha/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/mocha/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/mocha/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/mocha/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/mocha/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "vscode": "^1.71.0" + "node": ">=10" } }, - "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", - "dev": true, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "yallist": "^4.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=10" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, - "engines": { - "node": ">=6.9.0" + "dependencies": { + "randombytes": "^2.1.0" } }, - "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "shebang-regex": "^3.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=8" } }, - "node_modules/@types/node": { - "version": "8.10.66", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", - "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==", - "dev": true + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } }, - "node_modules/@types/vscode": { - "version": "1.87.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.87.0.tgz", - "integrity": "sha512-y3yYJV2esWr8LNjp3VNbSMWG7Y43jC8pCldG8YwiHGAQbsymkkMMt0aDT1xZIOFM2eFcNiUc+dJMx1+Z0UT8fg==", - "dev": true + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { - "sprintf-js": "~1.0.2" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==", + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { - "color-name": "1.1.3" + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "node_modules/supports-color": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", "dev": true, "engines": { - "node": ">=0.3.1" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, "engines": { - "node": ">=0.8.0" + "node": ">=6" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/glob": { + "node_modules/test-exclude/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", @@ -218,253 +2698,374 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=4" + "node": "*" } }, - "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.2" + "is-number": "^7.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=8.0" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "node_modules/ts-api-utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", + "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "dependencies": { - "hasown": "^2.0.0" + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "punycode": "^2.1.0" } }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/v8-to-istanbul": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" }, "engines": { - "node": "*" + "node": ">=10.12.0" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "engines": { + "node": ">=14.0.0" } }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, + "node_modules/vscode-languageclient": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", + "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", "dependencies": { - "minimist": "^1.2.6" + "minimatch": "^5.1.0", + "semver": "^7.3.7", + "vscode-languageserver-protocol": "3.17.5" }, - "bin": { - "mkdirp": "bin/cmd.js" + "engines": { + "vscode": "^1.82.0" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, + "node_modules/vscode-languageclient/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dependencies": { - "wrappy": "1" + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "node_modules/workerpool": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", "dev": true }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, - "bin": { - "resolve": "bin/resolve" + "engines": { + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, - "bin": { - "semver": "bin/semver" + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } }, - "node_modules/tslint": { - "version": "5.20.1", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", - "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.8.0", - "tsutils": "^2.29.0" - }, - "bin": { - "tslint": "bin/tslint" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=4.8.0" + "node": ">=12" }, - "peerDependencies": { - "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev" + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" } }, - "node_modules/tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "dependencies": { - "tslib": "^1.8.1" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, - "peerDependencies": { - "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" + "engines": { + "node": ">=12" } }, - "node_modules/typescript": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" }, "engines": { - "node": ">=4.2.0" + "node": ">=10" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/vscode-ext/package.json b/vscode-ext/package.json index ea6ec43..8f31983 100644 --- a/vscode-ext/package.json +++ b/vscode-ext/package.json @@ -1,21 +1,32 @@ { - "name": "heyvl", - "displayName": "HeyVL", - "description": "HeyVL language support", + "name": "caesar", + "displayName": "caesar", + "description": "VSCode Extension of the Deductive Probabilistic Program Verifier Caesar", "version": "0.0.1", "engines": { - "vscode": "^1.71.0" + "vscode": "^1.87.0" }, "categories": [ - "Programming Languages" + "Other" ], - "activationEvents": [], "main": "./out/extension.js", "contributes": { "commands": [ { - "command": "helloworld.helloWorld", - "title": "Hello World" + "command": "caesar.restartServer", + "title": "Caesar: Restart Server" + }, + { + "command": "caesar.startServer", + "title": "Caesar: Start Server" + }, + { + "command": "caesar.stopServer", + "title": "Caesar: Stop Server" + }, + { + "command": "caesar.verify", + "title": "Caesar: Verify" } ], "languages": [ @@ -37,17 +48,78 @@ "scopeName": "source.heyvl", "path": "./syntaxes/heyvl.tmLanguage.json" } + ], + "configuration": { + "type": "object", + "title": "Caesar", + "properties": { + "caesar.uI.gutterIcons.showGutterIcons": { + "type": "boolean", + "default": true, + "description": "Specifies whether to show icons on the gutter about the verification status." + }, + "caesar.uI.inlineGhostText.showInlineGhostText": { + "type": "boolean", + "default": true, + "description": "Specifies whether to show inline ghost text about the wp/wlp/ert." + }, + "caesar.uI.statusBar.showStatusBar": { + "type": "boolean", + "default": true, + "description": "Specifies whether to show the status bar." + }, + "caesar.automaticVerification": { + "type": "string", + "default": "onsave", + "enum": [ + "never", + "onsave" + ], + "description": "Specifies when Caesar automatically verifies the file." + } + } + }, + "colors": [ + { + "id": "caesar.inlineGhostBackgroundColor", + "description": "Specifies the background color of the inline ghost texts ", + "defaults": { + "dark": "#00000000", + "light": "#00000000", + "highContrast": "#00000000" + } + }, + { + "id": "caesar.inlineGhostForegroundColor", + "description": "Specifies the foreground color of the inline ghost texts", + "defaults": { + "dark": "#99999959", + "light": "#99999959", + "highContrast": "#99999999" + } + } ] }, "scripts": { "vscode:prepublish": "npm run compile", "compile": "tsc -p ./", - "watch": "tsc -watch -p ./" + "watch": "tsc -watch -p ./", + "pretest": "npm run compile && npm run lint", + "lint": "eslint src --ext ts", + "test": "vscode-test" }, "devDependencies": { - "@types/node": "^8.10.25", - "@types/vscode": "^1.71.0", - "tslint": "^5.16.0", - "typescript": "^3.4.5" + "@types/vscode": "^1.87.0", + "@types/mocha": "^10.0.6", + "@types/node": "18.x", + "@typescript-eslint/eslint-plugin": "^7.0.2", + "@typescript-eslint/parser": "^7.0.2", + "eslint": "^8.56.0", + "typescript": "^5.3.3", + "@vscode/test-cli": "^0.0.6", + "@vscode/test-electron": "^2.3.9" + }, + "dependencies": { + "vscode-languageclient": "9.0.1" } } diff --git a/caesar-ext/src/APIRegister.ts b/vscode-ext/src/APIRegister.ts similarity index 100% rename from caesar-ext/src/APIRegister.ts rename to vscode-ext/src/APIRegister.ts diff --git a/caesar-ext/src/Configuration.ts b/vscode-ext/src/Configuration.ts similarity index 100% rename from caesar-ext/src/Configuration.ts rename to vscode-ext/src/Configuration.ts diff --git a/vscode-ext/src/extension.ts b/vscode-ext/src/extension.ts index f2121b9..a3e4717 100644 --- a/vscode-ext/src/extension.ts +++ b/vscode-ext/src/extension.ts @@ -1,26 +1,129 @@ // The module 'vscode' contains the VS Code extensibility API // Import the module and reference it with the alias vscode in your code below import * as vscode from 'vscode'; +import * as path from 'path'; +import * as os from 'os'; +import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient/node'; +import { VerificationManager } from './manager/VerificationManager'; +import { GutterInformationView } from './view/GutterInformationView'; +import { StatusBarView } from './view/StatusBarView'; +import { State, StateManager } from './manager/StateManager'; +import { InlineGhostTextView } from './view/InlineGhostTextView'; +import { ViewCollection } from './view/ViewCollection'; +import APIRegister from './APIRegister'; -// this method is called when your extension is activated -// your extension is activated the very first time the command is executed + +let client: LanguageClient; +// This method is called when your extension is activated +// Your extension is activated the very first time the command is executed export function activate(context: vscode.ExtensionContext) { - // Use the console to output diagnostic information (console.log) and errors (console.error) - // This line of code will only be executed once when your extension is activated - console.log('Congratulations, your extension "helloworld-sample" is now active!'); - // The command has been defined in the package.json file - // Now provide the implementation of the command with registerCommand - // The commandId parameter must match the command field in package.json - let disposable = vscode.commands.registerCommand('helloworld.helloWorld', () => { - // The code you place here will be executed every time your command is executed + let serverExecutable = "cargo" + + // If the extension is launched in debug mode then the debug server options are used + // Otherwise the run options are used + let serverOptions: ServerOptions = { + run: { + command: serverExecutable, + args: ['run', '--', '--language-server'], + options: { cwd: path.resolve(os.homedir(), 'caesar') }, + }, + debug: { + command: serverExecutable, + args: ['run', '--', '--language-server'], + options: { cwd: path.resolve(os.homedir(), 'caesar') }, + } + }; + + // Options to control the language client + let clientOptions: LanguageClientOptions = { + diagnosticCollectionName: 'caesar', + // Register the server for heyvl documents + documentSelector: [{ scheme: 'file', language: 'heyvl' }], + synchronize: { + // Notify the server about file changes to '.clientrc files contained in the workspace + fileEvents: vscode.workspace.createFileSystemWatcher('**/*.heyvl') + } + }; + + // Create the language client and start the client. + client = new LanguageClient( + 'caesar', + 'Caesar', + serverOptions, + clientOptions + ); + + + // Initialize Managers + let verificationManager = new VerificationManager(client); + let stateManager = new StateManager(client); + + // // Initialize UI Views + let viewCollection = new ViewCollection(verificationManager, stateManager, context); + + + APIRegister.register('onDidSaveTextDocument', (textDocument) => { + if (textDocument.languageId === "heyvl") { + if (stateManager.getState() === State.Starting) { + return + } + const openEditor = vscode.window.visibleTextEditors.filter( + editor => editor.document.uri === textDocument.uri + )[0] + stateManager.setState(State.Verifying); + console.log("Verification Started") + + verificationManager.verify(openEditor, textDocument).then((_) => { + stateManager.setState(State.Finished) + }) + } + }); + - // Display a message box to the user - vscode.window.showInformationMessage('Hello World!'); - }); + vscode.commands.registerCommand('caesar.restartServer', async () => { + console.log("Restarting Caesar...") + client.restart() + }); + + vscode.commands.registerCommand('caesar.startServer', async () => { + console.log("Starting Caesar...") + client.start() + + }); + + vscode.commands.registerCommand('caesar.stopServer', async () => { + console.log("Stopping Caesar...") + client.stop() + }); + + vscode.commands.registerCommand('caesar.verify', async () => { + const openEditor = vscode.window.activeTextEditor + if (openEditor) { + stateManager.setState(State.Verifying); + console.log("Verification Started") + verificationManager.verify(openEditor, openEditor.document).then((_) => { + stateManager.setState(State.Finished) + }) + } + }); + + + // Submit all received callbacks to vscode api + APIRegister.submitAll(); + // Start the client. This will also launch the server + client.start(); + + console.log('Caesar is now active!'); + + + + // Add to a list of disposables which are disposed when this extension is deactivated. + context.subscriptions.push(viewCollection); + context.subscriptions.push(client); - context.subscriptions.push(disposable); } -// this method is called when your extension is deactivated +// This method is called when the extension is deactivated export function deactivate() { } + diff --git a/caesar-ext/src/manager/Manager.ts b/vscode-ext/src/manager/Manager.ts similarity index 100% rename from caesar-ext/src/manager/Manager.ts rename to vscode-ext/src/manager/Manager.ts diff --git a/caesar-ext/src/manager/StateManager.ts b/vscode-ext/src/manager/StateManager.ts similarity index 100% rename from caesar-ext/src/manager/StateManager.ts rename to vscode-ext/src/manager/StateManager.ts diff --git a/caesar-ext/src/manager/VerificationManager.ts b/vscode-ext/src/manager/VerificationManager.ts similarity index 100% rename from caesar-ext/src/manager/VerificationManager.ts rename to vscode-ext/src/manager/VerificationManager.ts diff --git a/caesar-ext/src/test/extension.test.ts b/vscode-ext/src/test/extension.test.ts similarity index 100% rename from caesar-ext/src/test/extension.test.ts rename to vscode-ext/src/test/extension.test.ts diff --git a/caesar-ext/src/utils.ts b/vscode-ext/src/utils.ts similarity index 100% rename from caesar-ext/src/utils.ts rename to vscode-ext/src/utils.ts diff --git a/caesar-ext/src/view/GutterInformationView.ts b/vscode-ext/src/view/GutterInformationView.ts similarity index 100% rename from caesar-ext/src/view/GutterInformationView.ts rename to vscode-ext/src/view/GutterInformationView.ts diff --git a/caesar-ext/src/view/InlineGhostTextView.ts b/vscode-ext/src/view/InlineGhostTextView.ts similarity index 100% rename from caesar-ext/src/view/InlineGhostTextView.ts rename to vscode-ext/src/view/InlineGhostTextView.ts diff --git a/caesar-ext/src/view/StatusBarView.ts b/vscode-ext/src/view/StatusBarView.ts similarity index 100% rename from caesar-ext/src/view/StatusBarView.ts rename to vscode-ext/src/view/StatusBarView.ts diff --git a/caesar-ext/src/view/View.ts b/vscode-ext/src/view/View.ts similarity index 100% rename from caesar-ext/src/view/View.ts rename to vscode-ext/src/view/View.ts diff --git a/caesar-ext/src/view/ViewCollection.ts b/vscode-ext/src/view/ViewCollection.ts similarity index 100% rename from caesar-ext/src/view/ViewCollection.ts rename to vscode-ext/src/view/ViewCollection.ts diff --git a/caesar-ext/tsconfig.json b/vscode-ext/tsconfig.json similarity index 100% rename from caesar-ext/tsconfig.json rename to vscode-ext/tsconfig.json diff --git a/vscode-ext/vsc-extension-quickstart.md b/vscode-ext/vsc-extension-quickstart.md index 10f6bca..3d8ce06 100644 --- a/vscode-ext/vsc-extension-quickstart.md +++ b/vscode-ext/vsc-extension-quickstart.md @@ -3,27 +3,41 @@ ## What's in the folder * This folder contains all of the files necessary for your extension. -* `package.json` - this is the manifest file in which you declare your language support and define the location of the grammar file that has been copied into your extension. -* `syntaxes/heyvl.tmLanguage.json` - this is the Text mate grammar file that is used for tokenization. -* `language-configuration.json` - this is the language configuration, defining the tokens that are used for comments and brackets. +* `package.json` - this is the manifest file in which you declare your extension and command. + * The sample plugin registers a command and defines its title and command name. With this information VS Code can show the command in the command palette. It doesn’t yet need to load the plugin. +* `src/extension.ts` - this is the main file where you will provide the implementation of your command. + * The file exports one function, `activate`, which is called the very first time your extension is activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`. + * We pass the function containing the implementation of the command as the second parameter to `registerCommand`. ## Get up and running straight away -* Make sure the language configuration settings in `language-configuration.json` are accurate. * Press `F5` to open a new window with your extension loaded. -* Create a new file with a file name suffix matching your language. -* Verify that syntax highlighting works and that the language configuration settings are working. +* Run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`. +* Set breakpoints in your code inside `src/extension.ts` to debug your extension. +* Find output from your extension in the debug console. ## Make changes -* You can relaunch the extension from the debug toolbar after making changes to the files listed above. +* You can relaunch the extension from the debug toolbar after changing code in `src/extension.ts`. * You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes. -## Add more language features +## Explore the API -* To add features such as IntelliSense, hovers and validators check out the VS Code extenders documentation at https://code.visualstudio.com/docs +* You can open the full set of our API when you open the file `node_modules/@types/vscode/index.d.ts`. -## Install your extension +## Run tests -* To start using your extension with Visual Studio Code copy it into the `/.vscode/extensions` folder and restart Code. -* To share your extension with the world, read on https://code.visualstudio.com/docs about publishing an extension. +* Install the [Extension Test Runner](https://marketplace.visualstudio.com/items?itemName=ms-vscode.extension-test-runner) +* Run the "watch" task via the **Tasks: Run Task** command. Make sure this is running, or tests might not be discovered. +* Open the Testing view from the activity bar and click the Run Test" button, or use the hotkey `Ctrl/Cmd + ; A` +* See the output of the test result in the Test Results view. +* Make changes to `src/test/extension.test.ts` or create new test files inside the `test` folder. + * The provided test runner will only consider files matching the name pattern `**.test.ts`. + * You can create folders inside the `test` folder to structure your tests any way you want. + +## Go further + +* [Follow UX guidelines](https://code.visualstudio.com/api/ux-guidelines/overview) to create extensions that seamlessly integrate with VS Code's native interface and patterns. + * Reduce the extension size and improve the startup time by [bundling your extension](https://code.visualstudio.com/api/working-with-extensions/bundling-extension). + * [Publish your extension](https://code.visualstudio.com/api/working-with-extensions/publishing-extension) on the VS Code extension marketplace. + * Automate builds by setting up [Continuous Integration](https://code.visualstudio.com/api/working-with-extensions/continuous-integration). From 6e6c7d9605e32f6ddefd96ab35c8b44b2fffa0e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Schro=CC=88er?= Date: Wed, 8 May 2024 10:11:23 +0200 Subject: [PATCH 10/25] build: revert change to linker settings for now this will be handled in a separate PR --- .cargo/config.toml | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .cargo/config.toml diff --git a/.cargo/config.toml b/.cargo/config.toml deleted file mode 100644 index 359ae44..0000000 --- a/.cargo/config.toml +++ /dev/null @@ -1,5 +0,0 @@ -[target.x86_64-unknown-linux-gnu] -rustflags = [ - "-C", "link-arg=-fuse-ld=lld", -] - From ff5ccaa26bf49e79a591525f5788551c93d7ecb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Schro=CC=88er?= Date: Wed, 8 May 2024 11:39:20 +0200 Subject: [PATCH 11/25] vscode-ext: move vscode settings --- {vscode-ext/.vscode => .vscode}/extensions.json | 0 {vscode-ext/.vscode => .vscode}/launch.json | 8 ++++---- .vscode/settings.json | 12 +++++++++--- {vscode-ext/.vscode => .vscode}/tasks.json | 4 +++- vscode-ext/.vscode/settings.json | 11 ----------- 5 files changed, 16 insertions(+), 19 deletions(-) rename {vscode-ext/.vscode => .vscode}/extensions.json (100%) rename {vscode-ext/.vscode => .vscode}/launch.json (68%) rename {vscode-ext/.vscode => .vscode}/tasks.json (78%) delete mode 100644 vscode-ext/.vscode/settings.json diff --git a/vscode-ext/.vscode/extensions.json b/.vscode/extensions.json similarity index 100% rename from vscode-ext/.vscode/extensions.json rename to .vscode/extensions.json diff --git a/vscode-ext/.vscode/launch.json b/.vscode/launch.json similarity index 68% rename from vscode-ext/.vscode/launch.json rename to .vscode/launch.json index 8880465..0338f74 100644 --- a/vscode-ext/.vscode/launch.json +++ b/.vscode/launch.json @@ -6,16 +6,16 @@ "version": "0.2.0", "configurations": [ { - "name": "Run Extension", + "name": "Run VSCode Extension", "type": "extensionHost", "request": "launch", "args": [ - "--extensionDevelopmentPath=${workspaceFolder}" + "--extensionDevelopmentPath=${workspaceFolder}/vscode-ext" ], "outFiles": [ - "${workspaceFolder}/out/**/*.js" + "${workspaceFolder}/vscode-ext/out/**/*.js" ], - "preLaunchTask": "${defaultBuildTask}" + "preLaunchTask": "VSCode Extension: npm watch" } ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index f075459..e6b786d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,10 @@ { - "cSpell.words": ["intern", "interner"], - "cSpell.enabled": false -} + "files.exclude": { + "vscode-ext/out": false // set this to true to hide the "out" folder with the compiled JS files + }, + "search.exclude": { + "vscode-ext/out": true // set this to false to include "out" folder in search results + }, + // Turn off tsc task auto detection since we have the necessary tasks as npm scripts + "typescript.tsc.autoDetect": "off" +} \ No newline at end of file diff --git a/vscode-ext/.vscode/tasks.json b/.vscode/tasks.json similarity index 78% rename from vscode-ext/.vscode/tasks.json rename to .vscode/tasks.json index 3b17e53..3bec11a 100644 --- a/vscode-ext/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -4,6 +4,8 @@ "version": "2.0.0", "tasks": [ { + "label": "VSCode Extension: npm watch", + "path": "vscode-ext", "type": "npm", "script": "watch", "problemMatcher": "$tsc-watch", @@ -13,7 +15,7 @@ }, "group": { "kind": "build", - "isDefault": true + "isDefault": false, } } ] diff --git a/vscode-ext/.vscode/settings.json b/vscode-ext/.vscode/settings.json deleted file mode 100644 index 30bf8c2..0000000 --- a/vscode-ext/.vscode/settings.json +++ /dev/null @@ -1,11 +0,0 @@ -// Place your settings in this file to overwrite default and user settings. -{ - "files.exclude": { - "out": false // set this to true to hide the "out" folder with the compiled JS files - }, - "search.exclude": { - "out": true // set this to false to include "out" folder in search results - }, - // Turn off tsc task auto detection since we have the necessary tasks as npm scripts - "typescript.tsc.autoDetect": "off" -} \ No newline at end of file From 218d45a28c9855641965e12f6f6f9bf642d72cd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Schro=CC=88er?= Date: Wed, 8 May 2024 11:45:03 +0200 Subject: [PATCH 12/25] Cargo.toml: remove settings that do not have an effect lto = false is default for profile.dev in Cargo --- Cargo.toml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index def7aaf..6723680 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ datatype-eureal = ["z3rro/datatype-eureal"] datatype-eureal-funcs = ["z3rro/datatype-eureal-funcs"] static-link-z3 = ["z3/static-link-z3"] # Emit log messages to stderr without timing information. This is useful to diff logs. -log-print-timeless = [] +log-print-timeless = [] [dependencies] string-interner = "0.12" @@ -69,10 +69,6 @@ name = "integration" path = "tests/integration.rs" harness = false -[profile.dev] -lto = false -# debug = false - [profile.release] # Debug information is nice, but it increases the binary size by about 500 megabytes. # So we don't enable it for release builds. From 62db4b0f4d13196349333b644b3af2b8eca2ccf1 Mon Sep 17 00:00:00 2001 From: umutdural Date: Wed, 8 May 2024 13:39:56 +0200 Subject: [PATCH 13/25] vscode-ext: removed duplicate code --- vscode-ext/src/utils.ts | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 vscode-ext/src/utils.ts diff --git a/vscode-ext/src/utils.ts b/vscode-ext/src/utils.ts deleted file mode 100644 index 4a83a4c..0000000 --- a/vscode-ext/src/utils.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as vscode from 'vscode'; - -const CONFIGURATION_SECTION = 'caesar'; - -export default class Configuration { - /// Get a configuration value from the configuration file with the given key - protected static getConfiguration(key: string): any { - const val: any | undefined = vscode.workspace.getConfiguration(CONFIGURATION_SECTION).get(key) - if (val === undefined) { - throw new Error(`${key} is not defined in the configuration file`); - } - return val; - } - - protected static getConfigurationPath(): string { - return "caesar." - } - -} From c82ea6305bd4be7388d5ea2f855fa945cad43026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Schro=CC=88er?= Date: Fri, 10 May 2024 17:52:55 +0200 Subject: [PATCH 14/25] refactor vscode-ext server --- src/ast/diagnostic.rs | 109 +++++-- src/driver.rs | 24 +- src/front/parser/mod.rs | 2 +- src/language_server/language_server.rs | 271 ------------------ src/language_server/mod.rs | 1 - src/main.rs | 180 ++++++------ src/servers/cli.rs | 76 +++++ src/servers/lsp.rs | 268 +++++++++++++++++ src/servers/mod.rs | 35 +++ src/servers/test.rs | 48 ++++ vscode-ext/src/extension.ts | 6 +- vscode-ext/src/manager/VerificationManager.ts | 28 +- vscode-ext/src/view/GutterInformationView.ts | 38 +-- vscode-ext/src/view/View.ts | 2 - vscode-ext/src/view/ViewCollection.ts | 5 +- 15 files changed, 645 insertions(+), 448 deletions(-) delete mode 100644 src/language_server/language_server.rs delete mode 100644 src/language_server/mod.rs create mode 100644 src/servers/cli.rs create mode 100644 src/servers/lsp.rs create mode 100644 src/servers/mod.rs create mode 100644 src/servers/test.rs diff --git a/src/ast/diagnostic.rs b/src/ast/diagnostic.rs index 3b1f10e..877d7c3 100644 --- a/src/ast/diagnostic.rs +++ b/src/ast/diagnostic.rs @@ -6,28 +6,33 @@ use std::{ error::Error, fmt::{self, Display, Formatter}, path::PathBuf, + sync::Arc, }; use ariadne::{Cache, Report, ReportBuilder, ReportKind, Source}; +use lsp_types::VersionedTextDocumentIdentifier; use pathdiff::diff_paths; use crate::pretty::{Doc, SimplePretty}; -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct FileId(u16); impl FileId { pub const DUMMY: FileId = FileId(0); } -#[derive(Debug)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum SourceFilePath { Path(PathBuf), + Lsp(VersionedTextDocumentIdentifier), Builtin, Generated, } impl SourceFilePath { + /// Rewrites a [`SourceFilePath::Path`] to be relative to the process + /// working directory. pub fn relative_to_cwd(&self) -> std::io::Result { match self { SourceFilePath::Path(path) => { @@ -37,18 +42,27 @@ impl SourceFilePath { let path_buf = diff_paths(path, current_dir).unwrap_or(path.to_path_buf()); Ok(SourceFilePath::Path(path_buf)) } - SourceFilePath::Builtin => Ok(SourceFilePath::Builtin), - SourceFilePath::Generated => Ok(SourceFilePath::Generated), + _ => Ok(self.clone()), } } pub fn to_string_lossy(&self) -> Cow<'_, str> { match self { SourceFilePath::Path(path) => path.to_string_lossy(), + SourceFilePath::Lsp(ident) => { + Cow::Owned(format!("{} (version {})", ident.uri, ident.version)) + } SourceFilePath::Builtin => Cow::from(""), SourceFilePath::Generated => Cow::from(""), } } + + pub fn to_lsp_identifier(&self) -> Option { + match self { + SourceFilePath::Lsp(ident) => Some(ident.clone()), + _ => None, + } + } } impl fmt::Display for SourceFilePath { @@ -101,7 +115,7 @@ impl fmt::Debug for StoredFile { #[derive(Debug, Default)] pub struct Files { - files: Vec, + files: Vec>, } impl Files { @@ -109,17 +123,43 @@ impl Files { Default::default() } - pub fn add(&mut self, path: SourceFilePath, source: String) -> &StoredFile { + pub fn add(&mut self, path: SourceFilePath, source: String) -> &Arc { let id = FileId(u16::try_from(self.files.len() + 1).unwrap()); - self.files.push(StoredFile::new(id, path, source)); - self.files.last().unwrap() + self.files.push(Arc::new(StoredFile::new(id, path, source))); + self.get(id).unwrap() + } + + pub fn add_or_update_uri( + &mut self, + document_id: VersionedTextDocumentIdentifier, + source: String, + ) -> &StoredFile { + let file = self.files.iter_mut().find(|file| { + if let SourceFilePath::Lsp(ident) = &file.path { + &ident.uri != &document_id.uri + } else { + true + } + }); + let path = SourceFilePath::Lsp(document_id); + if let Some(file) = file { + let file_id = file.id; + *file = Arc::new(StoredFile::new(file_id, path, source)); + self.get(file_id).unwrap() + } else { + self.add(path, source) + } } - pub fn get(&self, file_id: FileId) -> Option<&StoredFile> { + pub fn get(&self, file_id: FileId) -> Option<&Arc> { assert_ne!(file_id.0, 0); self.files.get((file_id.0 - 1) as usize) } + pub fn find(&self, path: &SourceFilePath) -> Option<&Arc> { + self.files.iter().find(|file| &file.path == path) + } + pub fn char_span(&self, span: Span) -> CharSpan { self.get(span.file).unwrap().char_span(span) } @@ -199,7 +239,10 @@ impl Span { } } - pub fn to_lsp_range(self, files: &Files) -> Option { + pub fn to_lsp( + self, + files: &Files, + ) -> Option<(VersionedTextDocumentIdentifier, lsp_types::Range)> { let file = files.get(self.file).unwrap(); let char_span = file.char_span(self); @@ -224,7 +267,7 @@ impl Span { } } - Some(lsp_types::Range { + let range = lsp_types::Range { start: lsp_types::Position { line: start_line, character: start_offset, @@ -233,7 +276,8 @@ impl Span { line: end_line, character: end_offset, }, - }) + }; + Some((file.path.to_lsp_identifier()?, range)) } } @@ -404,9 +448,16 @@ impl Diagnostic { builder } - pub fn into_lsp_diagnostic(self, files: &Files) -> lsp_types::Diagnostic { - let span = self.0.location; - let range = span.to_lsp_range(files).unwrap(); + pub fn span(&self) -> Span { + self.0.location + } + + pub fn into_lsp_diagnostic( + &self, + files: &Files, + ) -> Option<(VersionedTextDocumentIdentifier, lsp_types::Diagnostic)> { + let (document_id, range) = self.0.location.to_lsp(files)?; + let severity = match self.0.kind { ReportKind::Error => lsp_types::DiagnosticSeverity::ERROR, ReportKind::Warning => lsp_types::DiagnosticSeverity::WARNING, @@ -419,29 +470,32 @@ impl Diagnostic { .map(|code| lsp_types::NumberOrString::Number(code as i32)); let code_description = None; let source = None; - let message = self.0.msg.unwrap_or_else(|| "(no message)".to_string()); + let message = self + .0 + .msg + .clone() + .unwrap_or_else(|| "(no message)".to_string()); let related_information = self .0 .labels .iter() .flat_map(|label| { + let (uri, range) = if let Some(res) = label.span.to_lsp(files) { + res + } else { + tracing::error!("{:?} is not an LSP path, skipping label", label.span); + return None; + }; Some(lsp_types::DiagnosticRelatedInformation { location: lsp_types::Location { - uri: lsp_types::Url::parse( - format!( - "file://{}", - files.get(label.span.file).unwrap().path.to_string_lossy() - ) - .as_str(), - ) - .unwrap(), - range: label.span.to_lsp_range(files).unwrap(), + uri: uri.uri, + range, }, message: label.msg.clone()?, }) }) .collect::>(); - lsp_types::Diagnostic { + let diagnostic = lsp_types::Diagnostic { range, severity: Some(severity), code, @@ -451,7 +505,8 @@ impl Diagnostic { related_information: Some(related_information), tags: None, data: None, - } + }; + Some((document_id, diagnostic)) } /// Write the diagnostic to a simple [`String`] without ANSI colors. diff --git a/src/driver.rs b/src/driver.rs index 8ba71bf..252b18f 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -28,6 +28,7 @@ use crate::{ verify_proc, SpecCall, }, proof_rules::EncCall, + servers::Server, smt::{translate_exprs::TranslateExprs, SmtCtx}, tyctx::TyCtx, vc::{subst::apply_subst, vcgen::Vcgen}, @@ -302,15 +303,14 @@ impl SourceUnit { match self { SourceUnit::Decl(decl) => { match decl { - DeclKind::ProcDecl(proc_decl) => { - verify_proc(&proc_decl.borrow()).map(VerifyUnit) - } + DeclKind::ProcDecl(proc_decl) => verify_proc(&proc_decl.borrow()) + .map(|block| VerifyUnit(proc_decl.borrow().span, block)), DeclKind::DomainDecl(_domain_decl) => None, // TODO: check that the axioms are not contradictions DeclKind::FuncDecl(_func_decl) => None, _ => unreachable!(), // axioms and variable declarations are not allowed on the top level } } - SourceUnit::Raw(block) => Some(VerifyUnit(block)), + SourceUnit::Raw(_block) => todo!(), } } } @@ -333,14 +333,14 @@ impl fmt::Display for SourceUnit { /// A series of HeyVL statements to be verified. #[derive(Debug)] -pub struct VerifyUnit(Block); +pub struct VerifyUnit(Span, Block); impl VerifyUnit { /// Desugar some statements, such as assignments with procedure calls. #[instrument(skip(self, tcx))] pub fn desugar(&mut self, tcx: &mut TyCtx) -> Result<(), ()> { let mut spec_call = SpecCall::new(tcx); - spec_call.visit_stmts(&mut self.0) + spec_call.visit_stmts(&mut self.1) } /// Generate the verification conditions with post-expectation `∞`. @@ -352,7 +352,7 @@ impl VerifyUnit { ty: Some(TyKind::EUReal), span: Span::dummy_span(), }); - Ok(vcgen.vcgen_stmts(&self.0, infinity)) + Ok(vcgen.vcgen_stmts(&self.1, infinity)) } pub fn verify( @@ -360,6 +360,7 @@ impl VerifyUnit { name: &SourceUnitName, tcx: &mut TyCtx, options: &Options, + server: &mut dyn Server, ) -> Result { // 4. Desugaring: transforming spec calls to procs self.desugar(tcx).unwrap(); @@ -439,6 +440,13 @@ impl VerifyUnit { // Now let's examine the result. print_prove_result(result, name, &prover); } + let status = match result { + ProveResult::Proof => true, + ProveResult::Counterexample | ProveResult::Unknown => false, + }; + server + .set_verify_status(self.0, status) + .map_err(|err| VerifyError::ClientError(err))?; write_smtlib(options, smtlib, name, result).unwrap(); @@ -457,7 +465,7 @@ impl VerifyUnit { impl SimplePretty for VerifyUnit { fn pretty(&self) -> Doc { - self.0.pretty() + self.1.pretty() } } diff --git a/src/front/parser/mod.rs b/src/front/parser/mod.rs index 61b4488..2631686 100644 --- a/src/front/parser/mod.rs +++ b/src/front/parser/mod.rs @@ -13,7 +13,7 @@ use crate::ast::{ lalrpop_util::lalrpop_mod!( #[cfg_attr(rustfmt, rustfmt_skip)] - #[allow(clippy::all, unused_parens)] + #[allow(clippy::all, unused_parens, dead_code)] grammar, "/src/front/parser/grammar.rs" ); diff --git a/src/language_server/language_server.rs b/src/language_server/language_server.rs deleted file mode 100644 index 4845c3d..0000000 --- a/src/language_server/language_server.rs +++ /dev/null @@ -1,271 +0,0 @@ -use lsp_server::{Connection, Message, Request, Response}; -use lsp_types::{ - DidChangeTextDocumentParams, DidChangeWorkspaceFoldersParams, DidCloseTextDocumentParams, - DidOpenTextDocumentParams, ServerCapabilities, TextDocumentSyncCapability, - TextDocumentSyncKind, WorkspaceFolder, -}; -use lsp_types::{DidSaveTextDocumentParams, TextDocumentItem, Url}; - -use std::collections::HashMap; -use std::error::Error; - -use std::sync::Arc; -use std::sync::Mutex; - -use crate::ast::decl::DeclKind; -use crate::ast::{Files, Span}; -use crate::driver::{SourceUnit, SourceUnitName}; -use crate::{ - get_source_units_from_files, load_file, transform_source_to_verify, Options, VerifyError, -}; -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Serialize, Deserialize)] -struct VerificationStatusParams { - text_document: TextDocumentItem, -} - -impl lsp_types::request::Request for VerificationStatusParams { - type Params = VerificationStatusParams; - type Result = bool; - const METHOD: &'static str = "custom/verifyStatus"; -} - -pub fn run_server(options: &Options) -> Result<(), Box> { - let (connection, _) = Connection::stdio(); - let server_capabilities = ServerCapabilities { - text_document_sync: Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::NONE)), - - ..ServerCapabilities::default() - }; - - connection.initialize(serde_json::json!(server_capabilities))?; - - let mut documents = Arc::new(Mutex::new(Vec::new())); - let mut workspace_folders = Arc::new(Mutex::new(Vec::new())); - let mut proc_status_map: HashMap> = HashMap::new(); - - let start_notification = lsp_server::Notification::new("custom/serverReady".to_string(), ()); - let _ = connection - .sender - .send(Message::Notification(start_notification)); - - for msg in &connection.receiver { - match msg { - Message::Request(req) => { - handle_request( - req, - &connection, - options, - &mut documents, - &mut workspace_folders, - &mut proc_status_map, - )?; - } - Message::Notification(not) => { - handle_notification( - not, - &connection, - options, - &mut documents, - &mut workspace_folders, - &mut proc_status_map, - )?; - } - _ => (), - } - } - - Ok(()) -} - -fn handle_request( - req: Request, - connection: &Connection, - options: &Options, - _documents: &mut Arc>>, - _workspace_folders: &mut Arc>>, - _proc_status_map: &mut HashMap>, -) -> Result<(), Box> { - let response: Response = match req.method.as_str() { - "custom/verifyStatus" => { - let params: VerificationStatusParams = serde_json::from_value(req.params)?; - - let uri = params.text_document.uri; - - // TODO: Implement proper caching later. - let status_vec = match verify(options, uri.clone(), connection) { - Ok(vec) => { - let _ = clear_diagnostics(connection, uri.clone()); - vec - } - Err(_) => Vec::new(), - }; - - let proc_status_json = serde_json::to_value(status_vec)?; - Response::new_ok(req.id, proc_status_json) - } - _ => Response::new_err( - req.id, - lsp_server::ErrorCode::MethodNotFound as i32, - "Method not found".to_string(), - ), - }; - connection.sender.send(Message::Response(response))?; - Ok(()) -} - -fn handle_notification( - not: lsp_server::Notification, - _connection: &Connection, - _options: &Options, - documents: &mut Arc>>, - workspace_folders: &mut Arc>>, - proc_status_map: &mut HashMap>, -) -> Result<(), Box> { - match not.method.as_str() { - "textDocument/didOpen" => { - let params: DidOpenTextDocumentParams = serde_json::from_value(not.params.clone())?; - let uri = params.text_document.uri; - let text = params.text_document.text; - documents.lock().unwrap().push((uri.to_string(), text)); - - // verify_and_cache(options, uri, connection, proc_status_map); - } - "textDocument/didSave" => { - let params: DidSaveTextDocumentParams = serde_json::from_value(not.params.clone())?; - let uri = params.text_document.uri; - let text = params.text.unwrap(); - documents.lock().unwrap().push((uri.to_string(), text)); - - // verify_and_cache(uri, connection, proc_status_map); - } - "textDocument/didChange" => { - let params: DidChangeTextDocumentParams = serde_json::from_value(not.params.clone())?; - let _uri = params.text_document.uri; - // let _content_changes = params.content_changes; - // let mut _documents = documents.lock().unwrap(); - } - "textDocument/didClose" => { - let params: DidCloseTextDocumentParams = serde_json::from_value(not.params.clone())?; - let uri = params.text_document.uri; - documents - .lock() - .unwrap() - .retain(|(doc_uri, _)| !matches!(doc_uri.clone(), _uri)); - - proc_status_map.remove(&uri); - } - "workspace/didChangeWorkspaceFolders" => { - let params: DidChangeWorkspaceFoldersParams = - serde_json::from_value(not.params.clone())?; - let event = params.event; - let mut workspace_folders = workspace_folders.lock().unwrap(); - workspace_folders.extend(event.added.clone()); - workspace_folders.retain(|folder| !event.removed.contains(folder)); - } - _ => (), - } - Ok(()) -} - -fn report_diagnostics( - connection: &Connection, - uri: Url, - diagnostics: Vec, -) -> Result<(), Box> { - let params = lsp_types::PublishDiagnosticsParams { - uri, - diagnostics, - version: None, - }; - let notification = - lsp_server::Notification::new("textDocument/publishDiagnostics".to_string(), params); - connection - .sender - .send(lsp_server::Message::Notification(notification))?; - Ok(()) -} - -fn clear_diagnostics( - connection: &Connection, - uri: Url, -) -> Result<(), Box> { - let diagnostics = Vec::new(); - let params = lsp_types::PublishDiagnosticsParams { - uri, - diagnostics, - version: None, - }; - let notification = - lsp_server::Notification::new("textDocument/publishDiagnostics".to_string(), params); - connection - .sender - .send(lsp_server::Message::Notification(notification))?; - Ok(()) -} - -fn verify( - options: &Options, - uri: Url, - connection: &Connection, -) -> Result, ()> { - let path = uri - .to_file_path() - .expect("Failed to convert URI to file path"); - - let mut files = Files::new(); - let file_id = load_file(&mut files, &path); - - let files_mutex = Mutex::new(files); - - let mut proc_span_map: HashMap = HashMap::new(); - let mut local_proc_status: Vec<(lsp_types::Range, bool)> = Vec::new(); - - // We use a block to obtain a try-catch structure to catch the VerifyErrors that might be produced by 2 different function calls. - // The closure is needed to specify the return type of the block so that we can use the '?' operator. - let result = (|| -> Result<_, VerifyError> { - let (mut source_units, mut tcx) = - get_source_units_from_files(options, &files_mutex, &[file_id])?; - - let files = files_mutex.lock().unwrap(); - - source_units.iter_mut().for_each(|item| { - let (name, source_unit) = item.enter_with_name(); - if let SourceUnit::Decl(DeclKind::ProcDecl(ref proc_ref)) = *source_unit { - proc_span_map.insert(name.clone(), proc_ref.borrow().span); - } - }); - - let mut verify_units = transform_source_to_verify(options, source_units); - let mut all_proven: bool = true; - for verify_unit in &mut verify_units { - let (name, mut verify_unit) = verify_unit.enter_with_name(); - let result = verify_unit.verify(name, &mut tcx, options)?; - - if let Some(span) = proc_span_map.get(name) { - // let char_span = files.char_span(*span); - let range = (*span).to_lsp_range(&files).unwrap(); - local_proc_status.push((range, result)); - } - - all_proven = all_proven && result; - } - Ok(()) - })(); - - match result { - Ok(res) => res, - Err(e) => { - if let VerifyError::Diagnostic(diagnostic) = e { - let files = files_mutex.lock().unwrap(); - let diag = diagnostic.into_lsp_diagnostic(&files); - let _ = - report_diagnostics(connection, Url::from_file_path(path).unwrap(), vec![diag]); - return Err(()); - } - } - } - - Ok(local_proc_status) -} diff --git a/src/language_server/mod.rs b/src/language_server/mod.rs deleted file mode 100644 index 5c6cb9b..0000000 --- a/src/language_server/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod language_server; diff --git a/src/main.rs b/src/main.rs index adef37a..b264c76 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ use std::{ collections::HashMap, io, + ops::DerefMut, path::PathBuf, process::ExitCode, sync::{Arc, Mutex}, @@ -17,11 +18,11 @@ use crate::{ timing::TimingLayer, tyctx::TyCtx, }; -use ast::{Diagnostic, FileId, Files, SourceFilePath}; +use ast::{Diagnostic, FileId}; use driver::{Item, SourceUnit, VerifyUnit}; use intrinsic::{distributions::init_distributions, list::init_lists}; +use servers::{CliServer, LspServer, Server, ServerError}; -use language_server::language_server::run_server; use procs::add_default_specs; use proof_rules::init_encodings; use resource_limits::{await_with_resource_limits, LimitError}; @@ -36,13 +37,13 @@ pub mod ast; mod driver; pub mod front; pub mod intrinsic; -mod language_server; pub mod opt; pub mod pretty; mod procs; mod proof_rules; mod resource_limits; mod scope_map; +mod servers; mod smt; mod timing; pub mod tyctx; @@ -175,45 +176,40 @@ async fn main() -> ExitCode { // install global collector configured based on RUST_LOG env var. setup_tracing(&options); - let (timeout, mem_limit) = (options.timeout, options.mem_limit); - - // Run the language server and exit after it's done. - if options.language_server { - let result = run_server(&options); - if result.is_err() { - eprintln!("Error: {}", result.err().unwrap()); - return ExitCode::from(1); - } - return ExitCode::from(0); + if !options.language_server { + run_cli(options).await + } else { + run_server(&options).await } +} +async fn run_cli(options: Options) -> ExitCode { if options.files.is_empty() { eprintln!("Error: list of files must not be empty.\n"); return ExitCode::from(1); } - let mut files = Files::new(); + let mut client = CliServer::new(); let user_files: Vec = options .files .iter() - .map(|path| load_file(&mut files, path)) + .map(|path| client.load_file(path)) .collect(); let options = Arc::new(options); - let files = Arc::new(Mutex::new(files)); - - let verify_result = verify_files(&options, &files, user_files).await; + let server: Arc> = Arc::new(Mutex::new(client)); + let verify_result = verify_files(&options, &server, user_files).await; if options.timing { print_timings(); } + let (timeout, mem_limit) = (options.timeout, options.mem_limit); match verify_result { #[allow(clippy::bool_to_int_with_if)] Ok(all_verified) => ExitCode::from(if all_verified { 0 } else { 1 }), Err(VerifyError::Diagnostic(diagnostic)) => { - let files = files.lock().unwrap(); - print_diagnostic(&files, diagnostic).unwrap(); + server.lock().unwrap().add_diagnostic(diagnostic).unwrap(); ExitCode::from(1) } Err(VerifyError::IoError(err)) => { @@ -231,6 +227,7 @@ async fn main() -> ExitCode { ); std::process::exit(3); // exit ASAP } + Err(VerifyError::ClientError(err)) => panic!("{}", err), Err(VerifyError::Panic(join_error)) => panic!("{}", join_error), Err(VerifyError::Interrupted) => { tracing::error!("Interrupted"); @@ -239,6 +236,30 @@ async fn main() -> ExitCode { } } +async fn run_server(options: &Options) -> ExitCode { + let (mut client, _io_threads) = LspServer::connect_stdio(); + client.initialize().unwrap(); + let res = client.run_server(|client, user_files| { + let res = verify_files_main(options, client, user_files); + match res { + Ok(_) => Ok(()), + Err(VerifyError::Diagnostic(diag)) => { + client.add_diagnostic(diag).unwrap(); + Ok(()) + } + Err(err) => Err(err), + } + }); + match res { + Ok(()) => ExitCode::SUCCESS, + Err(VerifyError::Diagnostic(diag)) => { + client.add_diagnostic(diag).unwrap(); + ExitCode::FAILURE + } + Err(err) => panic!("{}", err), // TODO + } +} + /// Errors that can occur in the verifier. /// /// Note that some unit not verifying (solver yielding unknown or a @@ -251,6 +272,8 @@ pub enum VerifyError { IoError(#[from] io::Error), #[error("{0}")] LimitError(#[from] LimitError), + #[error("{0}")] + ClientError(ServerError), #[error("panic: {0}")] Panic(#[from] JoinError), #[error("interrupted")] @@ -262,13 +285,16 @@ pub enum VerifyError { /// command-line, such as in tests. pub async fn verify_files( options: &Arc, - files: &Arc>, + server: &Arc>, user_files: Vec, ) -> Result { let handle = { let options = options.clone(); - let files = files.clone(); - tokio::task::spawn_blocking(move || verify_files_main(&options, &files, &user_files)) + let client = server.clone(); + tokio::task::spawn_blocking(move || { + let mut client = client.lock().unwrap(); + verify_files_main(&options, client.deref_mut(), &user_files) + }) }; // Unpacking lots of results with `.await??` :-) await_with_resource_limits(options.timeout, options.mem_limit, handle).await?? @@ -277,32 +303,45 @@ pub async fn verify_files( /// Synchronously verify the given source code. This is used for tests. The /// `--werr` option is enabled by default. #[cfg(test)] -pub(crate) fn verify_test(source: &str) -> (Result, Files) { - let mut files = Files::new(); - let file_id = files.add(SourceFilePath::Builtin, source.to_owned()).id; - let files_mutex = Mutex::new(files); +pub(crate) fn verify_test(source: &str) -> (Result, servers::TestServer) { + use ast::SourceFilePath; + + let mut client = servers::TestServer::new(); + let file_id = client + .get_files_internal() + .lock() + .unwrap() + .add(SourceFilePath::Builtin, source.to_owned()) + .id; let mut options = Options::default(); options.werr = true; - let res = verify_files_main(&options, &files_mutex, &[file_id]); - (res, files_mutex.into_inner().unwrap()) + let res = verify_files_main(&options, &mut client, &[file_id]); + (res, client) } #[cfg(test)] pub(crate) fn single_desugar_test(source: &str) -> Result { - let mut files = Files::new(); - let file_id = files.add(SourceFilePath::Builtin, source.to_owned()).id; - let files_mutex = Mutex::new(files); - let options = Options::default(); + use ast::SourceFilePath; + + let mut client = servers::TestServer::new(); + let file_id = client + .get_files_internal() + .lock() + .unwrap() + .add(SourceFilePath::Builtin, source.to_owned()) + .id; + let mut options = Options::default(); + options.werr = true; - let mut files = files_mutex.lock().unwrap(); - let file = files.get(file_id).unwrap(); let mut source_units: Vec> = - SourceUnit::parse(file, options.raw).map_err(|parse_err| parse_err.diagnostic())?; + SourceUnit::parse(&client.get_file(file_id).unwrap(), options.raw) + .map_err(|parse_err| parse_err.diagnostic())?; let mut source_unit = source_units.remove(0); // 2. Resolving (and declaring) idents let mut tcx = TyCtx::new(TyKind::EUReal); + let mut files = client.get_files_internal().lock().unwrap(); init_encodings(&mut files, &mut tcx); init_distributions(&mut files, &mut tcx); init_lists(&mut files, &mut tcx); @@ -331,13 +370,9 @@ pub(crate) fn single_desugar_test(source: &str) -> Result { entered .tycheck(&mut tycheck) .map_err(|ty_err| ty_err.diagnostic())?; - let monotonicity_res = entered + entered .check_monotonicity() - .map_err(|ty_err| ty_err.diagnostic()); - if let Err(err) = monotonicity_res { - let files = files_mutex.lock().unwrap(); - print_warning(&options, &files, err)?; - } + .map_err(|ann_err| ann_err.diagnostic())?; } let mut new_source_units: Vec> = vec![]; // Desugar encodings from source units @@ -358,10 +393,10 @@ pub(crate) fn single_desugar_test(source: &str) -> Result { /// Synchronously verify the given files. fn verify_files_main( options: &Options, - files_mutex: &Mutex, + server: &mut dyn Server, user_files: &[FileId], ) -> Result { - let (source_units, mut tcx) = get_source_units_from_files(options, files_mutex, user_files)?; + let (source_units, mut tcx) = get_source_units_from_files(options, server, user_files)?; let mut verify_units = transform_source_to_verify(options, source_units); @@ -369,7 +404,7 @@ fn verify_files_main( for verify_unit in &mut verify_units { let (name, mut verify_unit) = verify_unit.enter_with_name(); - let result = verify_unit.verify(name, &mut tcx, options)?; + let result = verify_unit.verify(name, &mut tcx, options, server)?; all_proven = all_proven && result; } @@ -379,16 +414,15 @@ fn verify_files_main( pub fn get_source_units_from_files( options: &Options, - files_mutex: &Mutex, + server: &mut dyn Server, user_files: &[FileId], ) -> Result<(Vec>, TyCtx), VerifyError> { // 1. Parsing let mut source_units: Vec> = Vec::new(); - let mut files = files_mutex.lock().unwrap(); for file_id in user_files { - let file = files.get(*file_id).unwrap(); + let file = server.get_file(*file_id).unwrap(); let new_units = - SourceUnit::parse(file, options.raw).map_err(|parse_err| parse_err.diagnostic())?; + SourceUnit::parse(&file, options.raw).map_err(|parse_err| parse_err.diagnostic())?; // Print the result of parsing if requested if options.print_parsed { @@ -403,6 +437,7 @@ pub fn get_source_units_from_files( // 2. Resolving (and declaring) idents let mut tcx = TyCtx::new(TyKind::EUReal); + let mut files = server.get_files_internal().lock().unwrap(); init_encodings(&mut files, &mut tcx); init_distributions(&mut files, &mut tcx); init_lists(&mut files, &mut tcx); @@ -437,8 +472,9 @@ pub fn get_source_units_from_files( .check_monotonicity() .map_err(|ty_err| ty_err.diagnostic()); if let Err(err) = monotonicity_res { - let files = files_mutex.lock().unwrap(); - print_warning(options, &files, err)?; + server + .add_diagnostic(err) + .map_err(|e| VerifyError::ClientError(e))?; } } @@ -494,45 +530,3 @@ fn print_timings() { .collect(); eprintln!("Timings: {:?}", timings); } - -fn print_warning( - options: &Options, - files: &Files, - diagnostic: Diagnostic, -) -> Result<(), VerifyError> { - if !options.werr { - print_diagnostic(files, diagnostic)?; - Ok(()) - } else { - Err(diagnostic.into()) - } -} - -fn print_diagnostic(mut files: &Files, diagnostic: Diagnostic) -> io::Result<()> { - let mut report = diagnostic.into_ariadne(files); - if atty::isnt(atty::Stream::Stderr) { - // let's hope there's no config already there - report = report.with_config(ariadne::Config::default().with_color(false)); - } - let report = report.finish(); - report.eprint(&mut files) -} - -fn load_file(files: &mut Files, path: &PathBuf) -> FileId { - let source = match std::fs::read_to_string(path) { - Ok(source) => source, - Err(err) => match err.kind() { - io::ErrorKind::NotFound => { - panic!("Error: Could not find file '{}'", path.to_string_lossy()) - } - _ => panic!( - "Error while loading file '{}': {}", - path.to_string_lossy(), - err - ), - }, - }; - let source_file_path = SourceFilePath::Path(path.clone()); - let file = files.add(source_file_path, source); - file.id -} diff --git a/src/servers/cli.rs b/src/servers/cli.rs new file mode 100644 index 0000000..e579768 --- /dev/null +++ b/src/servers/cli.rs @@ -0,0 +1,76 @@ +use std::{ + io, + path::PathBuf, + sync::{Arc, Mutex}, +}; + +use crate::ast::{Diagnostic, FileId, Files, SourceFilePath, Span, StoredFile}; + +use super::{Server, ServerError}; + +pub struct CliServer { + files: Arc>, +} + +impl CliServer { + pub fn new() -> Self { + CliServer { + files: Default::default(), + } + } + + pub fn load_file(&mut self, path: &PathBuf) -> FileId { + let source = match std::fs::read_to_string(path) { + Ok(source) => source, + Err(err) => match err.kind() { + io::ErrorKind::NotFound => { + panic!("Error: Could not find file '{}'", path.to_string_lossy()) + } + _ => panic!( + "Error while loading file '{}': {}", + path.to_string_lossy(), + err + ), + }, + }; + let source_file_path = SourceFilePath::Path(path.clone()); + let mut files = self.files.lock().unwrap(); + let file = files.add(source_file_path, source); + file.id + } +} + +impl Server for CliServer { + fn send_server_ready(&self) -> Result<(), ServerError> { + Ok(()) + } + + fn get_file(&self, file_id: FileId) -> Option> { + self.files.lock().unwrap().get(file_id).cloned() + } + + fn get_files_internal(&mut self) -> &Mutex { + &self.files + } + + fn add_diagnostic(&mut self, diagnostic: Diagnostic) -> Result<(), ServerError> { + let files = self.files.lock().unwrap(); + print_diagnostic(&files, diagnostic)?; + Ok(()) + } + + fn set_verify_status(&mut self, _span: Span, _status: bool) -> Result<(), ServerError> { + // TODO + Ok(()) + } +} + +fn print_diagnostic(mut files: &Files, diagnostic: Diagnostic) -> io::Result<()> { + let mut report = diagnostic.into_ariadne(files); + if atty::isnt(atty::Stream::Stderr) { + // let's hope there's no config already there + report = report.with_config(ariadne::Config::default().with_color(false)); + } + let report = report.finish(); + report.eprint(&mut files) +} diff --git a/src/servers/lsp.rs b/src/servers/lsp.rs new file mode 100644 index 0000000..23f7dff --- /dev/null +++ b/src/servers/lsp.rs @@ -0,0 +1,268 @@ +use std::{ + collections::HashMap, + sync::{Arc, Mutex}, +}; + +use lsp_server::{Connection, IoThreads, Message, Response}; +use lsp_types::{ + DidChangeTextDocumentParams, DidCloseTextDocumentParams, DidOpenTextDocumentParams, + InitializeParams, ServerCapabilities, TextDocumentItem, TextDocumentSyncCapability, + TextDocumentSyncKind, VersionedTextDocumentIdentifier, +}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; + +use crate::{ + ast::{Diagnostic, FileId, Files, SourceFilePath, Span, StoredFile}, + VerifyError, +}; + +use super::{Server, ServerError}; + +#[derive(Debug, Serialize, Deserialize)] +struct VerifyStatusRequest { + text_document: VersionedTextDocumentIdentifier, +} + +#[derive(Debug, Serialize, Deserialize)] +struct VerifyStatusUpdate { + document: VersionedTextDocumentIdentifier, + statuses: Vec<(lsp_types::Range, bool)>, +} + +/// A connection to an LSP client. +pub struct LspServer { + project_root: Option, + files: Arc>, + connection: Connection, + diagnostics: Vec, + statuses: HashMap, +} + +impl LspServer { + const HEYVL_LANGUAGE_IDENTIFIER: &'static str = "heyvl"; + + /// Create a new client connection on stdin and stdout. + pub fn connect_stdio() -> (LspServer, IoThreads) { + let (connection, io_threads) = Connection::stdio(); + let connection = LspServer { + project_root: None, + files: Default::default(), + connection, + diagnostics: Default::default(), + statuses: Default::default(), + }; + (connection, io_threads) + } + + pub fn initialize(&mut self) -> Result<(), ServerError> { + let server_capabilities = ServerCapabilities { + text_document_sync: Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::FULL)), + ..ServerCapabilities::default() + }; + let res = self + .connection + .initialize(serde_json::json!(server_capabilities))?; + let _init_params: InitializeParams = serde_json::from_value(res)?; + + // TODO: just use the initialization result in the client + let start_notification = + lsp_server::Notification::new("custom/serverReady".to_string(), ()); + self.connection + .sender + .send(Message::Notification(start_notification))?; + + Ok(()) + } + + pub fn run_server( + &mut self, + mut verify: impl FnMut(&mut Self, &[FileId]) -> Result<(), VerifyError>, + ) -> Result<(), VerifyError> { + let sender = self.connection.sender.clone(); + let receiver = self.connection.receiver.clone(); + for msg in &receiver { + match msg { + Message::Request(req) => match req.method.as_str() { + "custom/verifyStatus" => { + let (id, params) = req + .extract::("custom/verifyStatus") + .map_err(|e| VerifyError::ClientError(e.into()))?; + self.project_root = Some(params.text_document.clone()); + let files = self.files.lock().unwrap(); + let file_id = files + .find(&SourceFilePath::Lsp(params.text_document.clone())) + .unwrap() + .id; + drop(files); + self.clear_all(); + verify(self, &[file_id])?; + sender + .send(Message::Response(Response::new_ok(id, Value::Null))) + .map_err(|e| VerifyError::ClientError(e.into()))?; + } + _ => {} // TODO + }, + Message::Response(_) => todo!(), + Message::Notification(notification) => { + self.handle_notification(notification) + .map_err(|e| VerifyError::ClientError(e.into()))?; + } + } + } + Ok(()) + } + + fn handle_notification( + &mut self, + notification: lsp_server::Notification, + ) -> Result, ServerError> { + match notification.method.as_str() { + "textDocument/didOpen" => { + let params: DidOpenTextDocumentParams = + notification.extract("textDocument/didOpen")?; + self.update_text_document(params.text_document); + Ok(None) + } + "textDocument/didChange" => { + let params: DidChangeTextDocumentParams = + notification.extract("textDocument/didChange")?; + assert_eq!(params.content_changes.len(), 1); + let latest = params.content_changes.into_iter().last().unwrap(); + let text_document = TextDocumentItem { + uri: params.text_document.uri, + language_id: Self::HEYVL_LANGUAGE_IDENTIFIER.to_owned(), + version: params.text_document.version, + text: latest.text, + }; + self.update_text_document(text_document); + Ok(None) + } + "textDocument/didClose" => { + let _params: DidCloseTextDocumentParams = + notification.extract("textDocument/didClose")?; + // TODO: remove file? + Ok(None) + } + _ => Ok(Some(notification)), + } + } + + fn update_text_document(&mut self, document: TextDocumentItem) { + if document.language_id != Self::HEYVL_LANGUAGE_IDENTIFIER { + return; + } + let document_id = VersionedTextDocumentIdentifier { + uri: document.uri, + version: document.version, + }; + self.files + .lock() + .unwrap() + .add_or_update_uri(document_id, document.text); + self.clear_all(); + } + + fn publish_diagnostics(&mut self) -> Result<(), ServerError> { + let files = self.files.lock().unwrap(); + let diags_by_document = by_lsp_document( + &files, + self.diagnostics + .iter() + .map(|diagnostic| (diagnostic.span().file, diagnostic)), + ); + for (document_id, diagnostics) in diags_by_document { + let diagnostics = diagnostics + .iter() + .map(|diag| diag.into_lsp_diagnostic(&files).unwrap().1) + .collect(); + let params = lsp_types::PublishDiagnosticsParams { + uri: document_id.uri, + diagnostics, + version: Some(document_id.version), + }; + let notification = lsp_server::Notification::new( + "textDocument/publishDiagnostics".to_string(), + params, + ); + self.connection + .sender + .send(lsp_server::Message::Notification(notification))?; + } + Ok(()) + } + + fn publish_verify_statuses(&self) -> Result<(), ServerError> { + let files = self.files.lock().unwrap(); + let statuses_by_document = by_lsp_document( + &files, + self.statuses.iter().flat_map(|(span, status)| { + let (_, range) = span.to_lsp(&files)?; + Some((span.file, (range, *status))) + }), + ); + for (document_id, statuses) in statuses_by_document { + let params = VerifyStatusUpdate { + document: document_id, + statuses, + }; + let notification = + lsp_server::Notification::new("custom/verifyStatus".to_string(), params); + dbg!(¬ification); + self.connection + .sender + .send(lsp_server::Message::Notification(notification))?; + } + Ok(()) + } + + fn clear_all(&mut self) { + self.diagnostics.clear(); + self.statuses.clear(); + } +} + +impl Server for LspServer { + fn send_server_ready(&self) -> Result<(), ServerError> { + let start_notification = + lsp_server::Notification::new("custom/serverReady".to_string(), ()); + self.connection + .sender + .send(Message::Notification(start_notification))?; + Ok(()) + } + + fn get_file(&self, file_id: FileId) -> Option> { + self.files.lock().unwrap().get(file_id).cloned() + } + + fn get_files_internal(&mut self) -> &Mutex { + &self.files + } + + fn add_diagnostic(&mut self, diagnostic: Diagnostic) -> Result<(), ServerError> { + self.diagnostics.push(diagnostic); + self.publish_diagnostics()?; + Ok(()) + } + + fn set_verify_status(&mut self, span: Span, status: bool) -> Result<(), ServerError> { + self.statuses.insert(span, status); + self.publish_verify_statuses()?; + Ok(()) + } +} + +fn by_lsp_document<'a, T: 'a>( + files: &'a Files, + iter: impl IntoIterator, +) -> impl Iterator)> + 'a { + let mut by_file: HashMap> = HashMap::new(); + for (file_id, val) in iter.into_iter() { + by_file.entry(file_id).or_default().push(val); + } + by_file.into_iter().flat_map(move |(file_id, vals)| { + let document_id = files.get(file_id).unwrap().path.to_lsp_identifier()?; + Some((document_id, vals)) + }) +} diff --git a/src/servers/mod.rs b/src/servers/mod.rs new file mode 100644 index 0000000..9744a60 --- /dev/null +++ b/src/servers/mod.rs @@ -0,0 +1,35 @@ +use std::{ + error::Error, + sync::{Arc, Mutex}, +}; + +use crate::ast::{Diagnostic, FileId, Files, Span, StoredFile}; + +mod cli; +mod lsp; +#[cfg(test)] +mod test; + +pub use cli::CliServer; +pub use lsp::LspServer; +#[cfg(test)] +pub use test::TestServer; + +pub type ServerError = Box; + +/// A server that serves information to a client, such as the CLI or an LSP +/// client. +pub trait Server: Send { + /// Send our custom `serverReady` notification to the client. + fn send_server_ready(&self) -> Result<(), ServerError>; + + fn get_file(&self, file_id: FileId) -> Option>; + + fn get_files_internal(&mut self) -> &Mutex; + + /// Add a new [`Diagnostic`]. + fn add_diagnostic(&mut self, diagnostic: Diagnostic) -> Result<(), ServerError>; + + /// Send a verification status message to the client (a custom notification). + fn set_verify_status(&mut self, span: Span, status: bool) -> Result<(), ServerError>; +} diff --git a/src/servers/test.rs b/src/servers/test.rs new file mode 100644 index 0000000..532a9e3 --- /dev/null +++ b/src/servers/test.rs @@ -0,0 +1,48 @@ +use std::{ + collections::HashMap, + sync::{Arc, Mutex}, +}; + +use crate::ast::{Diagnostic, FileId, Files, Span, StoredFile}; + +use super::{Server, ServerError}; + +pub struct TestServer { + pub files: Arc>, + pub diagnostics: Vec, + pub statuses: HashMap, +} + +impl TestServer { + pub fn new() -> Self { + TestServer { + files: Default::default(), + diagnostics: Default::default(), + statuses: Default::default(), + } + } +} + +impl Server for TestServer { + fn send_server_ready(&self) -> Result<(), ServerError> { + Ok(()) + } + + fn get_file(&self, file_id: FileId) -> Option> { + self.files.lock().unwrap().get(file_id).cloned() + } + + fn get_files_internal(&mut self) -> &Mutex { + &self.files + } + + fn add_diagnostic(&mut self, diagnostic: Diagnostic) -> Result<(), ServerError> { + self.diagnostics.push(diagnostic); + Ok(()) + } + + fn set_verify_status(&mut self, span: Span, status: bool) -> Result<(), ServerError> { + self.statuses.insert(span, status); + Ok(()) + } +} diff --git a/vscode-ext/src/extension.ts b/vscode-ext/src/extension.ts index a3e4717..da09751 100644 --- a/vscode-ext/src/extension.ts +++ b/vscode-ext/src/extension.ts @@ -60,8 +60,7 @@ export function activate(context: vscode.ExtensionContext) { let stateManager = new StateManager(client); // // Initialize UI Views - let viewCollection = new ViewCollection(verificationManager, stateManager, context); - + let viewCollection = new ViewCollection(verificationManager, stateManager, context, client); APIRegister.register('onDidSaveTextDocument', (textDocument) => { if (textDocument.languageId === "heyvl") { @@ -89,7 +88,6 @@ export function activate(context: vscode.ExtensionContext) { vscode.commands.registerCommand('caesar.startServer', async () => { console.log("Starting Caesar...") client.start() - }); vscode.commands.registerCommand('caesar.stopServer', async () => { @@ -116,8 +114,6 @@ export function activate(context: vscode.ExtensionContext) { console.log('Caesar is now active!'); - - // Add to a list of disposables which are disposed when this extension is deactivated. context.subscriptions.push(viewCollection); context.subscriptions.push(client); diff --git a/vscode-ext/src/manager/VerificationManager.ts b/vscode-ext/src/manager/VerificationManager.ts index 9615367..2c10bf5 100644 --- a/vscode-ext/src/manager/VerificationManager.ts +++ b/vscode-ext/src/manager/VerificationManager.ts @@ -1,47 +1,33 @@ import * as vscode from "vscode"; -import { LanguageClient } from "vscode-languageclient/node"; +import { LanguageClient, VersionedTextDocumentIdentifier } from "vscode-languageclient/node"; import { Manager, Observer } from "./Manager"; import APIRegister from "../APIRegister"; -export type VerificationStatus = Array<[vscode.Range, boolean]>; +export type VerificationStatus = { + document: VersionedTextDocumentIdentifier, + statuses: Array<[vscode.Range, boolean]>, +}; export class VerificationManager extends Manager { private client: LanguageClient; - // private verificationStatus: Map = new Map(); - private verificationStatus: VerificationStatus = []; constructor(client: LanguageClient) { super(); this.client = client; - - } - - public getStatus(editor: vscode.TextEditor): VerificationStatus { - // return this.verificationStatus.get(editor) || []; - return this.verificationStatus; } - public setStatus(editor: vscode.TextEditor, newStatus: VerificationStatus): void { - // this.verificationStatus.set(editor, newStatus); - this.verificationStatus = newStatus; - this.notify(this.verificationStatus); - } - - - public async verify(editor: vscode.TextEditor, document: vscode.TextDocument): Promise { + public async verify(editor: vscode.TextEditor, document: vscode.TextDocument): Promise { let documentItem = { uri: document.uri.toString(), languageId: document.languageId, version: document.version, text: document.getText() } - let response: VerificationStatus = await this.client.sendRequest('custom/verifyStatus', { text_document: documentItem }); - this.setStatus(editor, response); - return response; + await this.client.sendRequest('custom/verifyStatus', { text_document: documentItem }); } } diff --git a/vscode-ext/src/view/GutterInformationView.ts b/vscode-ext/src/view/GutterInformationView.ts index 6fc14a2..1ada0f8 100644 --- a/vscode-ext/src/view/GutterInformationView.ts +++ b/vscode-ext/src/view/GutterInformationView.ts @@ -5,6 +5,8 @@ import { Manager, Observer } from "../manager/Manager"; import Configuration, { CONFIGURATION_SECTION, ConfigCategory, GutterInformationViewConfig } from "../Configuration"; import APIRegister from "../APIRegister"; import { EditorView } from "./View"; +import { VersionedTextDocumentIdentifier } from "vscode-languageclient"; +import { LanguageClient } from "vscode-languageclient/node"; @@ -30,9 +32,9 @@ export class GutterInformationView extends EditorView { private failedDecType: vscode.TextEditorDecorationType; private unknownDecType: vscode.TextEditorDecorationType; - private procStatus: VerificationStatus = []; + private procStatus?: VerificationStatus; - constructor(verificationManager: VerificationManager, context: vscode.ExtensionContext) { + constructor(verificationManager: VerificationManager, context: vscode.ExtensionContext, client: LanguageClient) { super(); this.enabled = GutterInformationViewConfig.get("showGutterIcons"); @@ -54,6 +56,10 @@ export class GutterInformationView extends EditorView { } } }); + + client.onNotification("custom/verifyStatus", (params: VerificationStatus) => { + this.receiveVerificationUpdate(params); + }) } /// Enable the GutterInformationView @@ -96,24 +102,22 @@ export class GutterInformationView extends EditorView { /// Update the checkmarks based on the latest verification status received from the VerificationManager public updateView(editor: vscode.TextEditor) { - if (this.procStatus.length === 0 || !this.enabled) { - return; - } const verifiedProcs: vscode.DecorationOptions[] = []; const failedProcs: vscode.DecorationOptions[] = []; const unknownProcs: vscode.DecorationOptions[] = []; - - for (const proc of this.procStatus) { - const verified = proc[1]; - - const line = proc[0].start.line; - const range = new vscode.Range(line, 0, line, 0); - if (verified) { - // Put the checkmark before the proc. - verifiedProcs.push({ range, hoverMessage: 'Verified' }); - } else { - // Put the X before the proc. - failedProcs.push({ range, hoverMessage: 'Not Verified' }); + if (this.enabled && this.procStatus != null && this.procStatus.document.uri == editor.document.uri.toString()) { + for (const proc of this.procStatus.statuses) { + const verified = proc[1]; + + const line = proc[0].start.line; + const range = new vscode.Range(line, 0, line, 0); + if (verified) { + // Put the checkmark before the proc. + verifiedProcs.push({ range, hoverMessage: 'Verified' }); + } else { + // Put the X before the proc. + failedProcs.push({ range, hoverMessage: 'Not Verified' }); + } } } editor.setDecorations(this.verifyDecType, verifiedProcs); diff --git a/vscode-ext/src/view/View.ts b/vscode-ext/src/view/View.ts index f0d2f7b..fd72df8 100644 --- a/vscode-ext/src/view/View.ts +++ b/vscode-ext/src/view/View.ts @@ -2,7 +2,6 @@ import * as vscode from 'vscode'; export abstract class EditorView { - public abstract updateView(update: any): void; public abstract clearView(editor: vscode.TextEditor): void; @@ -14,5 +13,4 @@ export abstract class EditorView { editors.forEach(editor => this.clearView(editor)); } - } diff --git a/vscode-ext/src/view/ViewCollection.ts b/vscode-ext/src/view/ViewCollection.ts index 54f77f6..1902d04 100644 --- a/vscode-ext/src/view/ViewCollection.ts +++ b/vscode-ext/src/view/ViewCollection.ts @@ -5,6 +5,7 @@ import { VerificationManager } from "../manager/VerificationManager"; import { GutterInformationView } from "./GutterInformationView"; import { InlineGhostTextView } from "./InlineGhostTextView"; import { StatusBarView } from "./StatusBarView"; +import { LanguageClient } from "vscode-languageclient/node"; /// A container for all the views in the extension @@ -15,8 +16,8 @@ export class ViewCollection { public inlineGhostText: InlineGhostTextView | null; - constructor(verificationManager: VerificationManager, stateManager: StateManager, context: vscode.ExtensionContext) { - this.gutterInfo = new GutterInformationView(verificationManager, context); + constructor(verificationManager: VerificationManager, stateManager: StateManager, context: vscode.ExtensionContext, client: LanguageClient) { + this.gutterInfo = new GutterInformationView(verificationManager, context, client); this.statusBar = new StatusBarView(stateManager); this.inlineGhostText = new InlineGhostTextView(verificationManager); } From 1a8590bc37efe3c5cb835898da11dfd5b55d2437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Schro=CC=88er?= Date: Fri, 10 May 2024 20:27:37 +0200 Subject: [PATCH 15/25] re-add support for --werr for cli and test servers it's not yet supported for the lsp server, as that is a bit more complicated. the main reason to fix this now is to fix the unit tests which rely on --werr --- src/ast/diagnostic.rs | 12 ++++++++---- src/main.rs | 26 +++++++++++++------------- src/servers/cli.rs | 14 ++++++++++---- src/servers/lsp.rs | 15 +++++++++++---- src/servers/mod.rs | 19 ++++++++++++++++--- src/servers/test.rs | 16 +++++++++++----- 6 files changed, 69 insertions(+), 33 deletions(-) diff --git a/src/ast/diagnostic.rs b/src/ast/diagnostic.rs index bad847d..7a931c9 100644 --- a/src/ast/diagnostic.rs +++ b/src/ast/diagnostic.rs @@ -457,6 +457,14 @@ impl Diagnostic { self } + pub fn kind(&self) -> ReportKind { + self.0.kind + } + + pub fn span(&self) -> Span { + self.0.location + } + /// Generate the [`ariadne::ReportBuilder`]. pub fn into_ariadne(self, files: &Files) -> ReportBuilder { // note that ariadne's report doesn't use the span end @@ -477,10 +485,6 @@ impl Diagnostic { builder } - pub fn span(&self) -> Span { - self.0.location - } - pub fn into_lsp_diagnostic( &self, files: &Files, diff --git a/src/main.rs b/src/main.rs index a2edd20..5a2ed0d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -214,7 +214,7 @@ async fn run_cli(options: Options) -> ExitCode { return ExitCode::from(1); } - let mut client = CliServer::new(); + let mut client = CliServer::new(&options); let user_files: Vec = options .files .iter() @@ -333,15 +333,17 @@ pub async fn verify_files( pub(crate) fn verify_test(source: &str) -> (Result, servers::TestServer) { use ast::SourceFilePath; - let mut server = servers::TestServer::new(); + let mut options = Options::default(); + options.werr = true; + + let mut server = servers::TestServer::new(&options); let file_id = server .get_files_internal() .lock() .unwrap() .add(SourceFilePath::Builtin, source.to_owned()) .id; - let mut options = Options::default(); - options.werr = true; + let options = Arc::new(options); let limits_ref = LimitsRef::new(None); let res = verify_files_main(&options, limits_ref, &mut server, &[file_id]); @@ -352,15 +354,16 @@ pub(crate) fn verify_test(source: &str) -> (Result, servers:: pub(crate) fn single_desugar_test(source: &str) -> Result { use ast::SourceFilePath; - let mut client = servers::TestServer::new(); + let mut options = Options::default(); + options.werr = true; + + let mut client = servers::TestServer::new(&options); let file_id = client .get_files_internal() .lock() .unwrap() .add(SourceFilePath::Builtin, source.to_owned()) .id; - let mut options = Options::default(); - options.werr = true; let mut source_units: Vec> = SourceUnit::parse(&client.get_file(file_id).unwrap(), options.raw) @@ -371,6 +374,7 @@ pub(crate) fn single_desugar_test(source: &str) -> Result { // 2. Resolving (and declaring) idents let mut tcx = TyCtx::new(TyKind::EUReal); let mut files = client.get_files_internal().lock().unwrap(); + init_calculi(&mut files, &mut tcx); init_encodings(&mut files, &mut tcx); init_distributions(&mut files, &mut tcx); init_lists(&mut files, &mut tcx); @@ -462,9 +466,7 @@ fn verify_files_main( let monotonicity_res = source_unit.check_monotonicity(); if let Err(err) = monotonicity_res { - server - .add_diagnostic(err) - .map_err(VerifyError::ServerError)?; + server.add_diagnostic(err)?; } } @@ -473,9 +475,7 @@ fn verify_files_main( let source_unit = source_unit.enter(); let jani_res = source_unit.write_to_jani_if_requested(options, &tcx); match jani_res { - Err(VerifyError::Diagnostic(diagnostic)) => server - .add_diagnostic(diagnostic) - .map_err(VerifyError::ServerError)?, + Err(VerifyError::Diagnostic(diagnostic)) => server.add_diagnostic(diagnostic)?, Err(err) => Err(err)?, _ => (), } diff --git a/src/servers/cli.rs b/src/servers/cli.rs index e579768..5b93424 100644 --- a/src/servers/cli.rs +++ b/src/servers/cli.rs @@ -4,17 +4,22 @@ use std::{ sync::{Arc, Mutex}, }; -use crate::ast::{Diagnostic, FileId, Files, SourceFilePath, Span, StoredFile}; +use crate::{ + ast::{Diagnostic, FileId, Files, SourceFilePath, Span, StoredFile}, + Options, VerifyError, +}; -use super::{Server, ServerError}; +use super::{unless_fatal_error, Server, ServerError}; pub struct CliServer { + werr: bool, files: Arc>, } impl CliServer { - pub fn new() -> Self { + pub fn new(options: &Options) -> Self { CliServer { + werr: options.werr, files: Default::default(), } } @@ -53,7 +58,8 @@ impl Server for CliServer { &self.files } - fn add_diagnostic(&mut self, diagnostic: Diagnostic) -> Result<(), ServerError> { + fn add_diagnostic(&mut self, diagnostic: Diagnostic) -> Result<(), VerifyError> { + let diagnostic = unless_fatal_error(self.werr, diagnostic)?; let files = self.files.lock().unwrap(); print_diagnostic(&files, diagnostic)?; Ok(()) diff --git a/src/servers/lsp.rs b/src/servers/lsp.rs index 094352a..db0a017 100644 --- a/src/servers/lsp.rs +++ b/src/servers/lsp.rs @@ -96,10 +96,15 @@ impl LspServer { .id; drop(files); self.clear_all(); - verify(self, &[file_id])?; + let result = verify(self, &[file_id]); + let res = match &result { + Ok(_) => Response::new_ok(id, Value::Null), + Err(err) => Response::new_err(id, 0, format!("{}", err)), + }; sender - .send(Message::Response(Response::new_ok(id, Value::Null))) + .send(Message::Response(res)) .map_err(|e| VerifyError::ServerError(e.into()))?; + result?; } } Message::Response(_) => todo!(), @@ -239,9 +244,11 @@ impl Server for LspServer { &self.files } - fn add_diagnostic(&mut self, diagnostic: Diagnostic) -> Result<(), ServerError> { + fn add_diagnostic(&mut self, diagnostic: Diagnostic) -> Result<(), VerifyError> { + // TODO: add --werr support self.diagnostics.push(diagnostic); - self.publish_diagnostics()?; + self.publish_diagnostics() + .map_err(VerifyError::ServerError)?; Ok(()) } diff --git a/src/servers/mod.rs b/src/servers/mod.rs index 9744a60..8d416bb 100644 --- a/src/servers/mod.rs +++ b/src/servers/mod.rs @@ -3,13 +3,17 @@ use std::{ sync::{Arc, Mutex}, }; -use crate::ast::{Diagnostic, FileId, Files, Span, StoredFile}; +use crate::{ + ast::{Diagnostic, FileId, Files, Span, StoredFile}, + VerifyError, +}; mod cli; mod lsp; #[cfg(test)] mod test; +use ariadne::ReportKind; pub use cli::CliServer; pub use lsp::LspServer; #[cfg(test)] @@ -27,9 +31,18 @@ pub trait Server: Send { fn get_files_internal(&mut self) -> &Mutex; - /// Add a new [`Diagnostic`]. - fn add_diagnostic(&mut self, diagnostic: Diagnostic) -> Result<(), ServerError>; + /// Add a new [`Diagnostic`]. Abort with a [`VerifyError::Diagnostic`] if + /// the diagnostic is fatal. + fn add_diagnostic(&mut self, diagnostic: Diagnostic) -> Result<(), VerifyError>; /// Send a verification status message to the client (a custom notification). fn set_verify_status(&mut self, span: Span, status: bool) -> Result<(), ServerError>; } + +fn unless_fatal_error(werr: bool, diagnostic: Diagnostic) -> Result { + if diagnostic.kind() == ReportKind::Error || werr { + Err(VerifyError::Diagnostic(diagnostic)) + } else { + Ok(diagnostic) + } +} diff --git a/src/servers/test.rs b/src/servers/test.rs index 532a9e3..c4afddd 100644 --- a/src/servers/test.rs +++ b/src/servers/test.rs @@ -3,20 +3,25 @@ use std::{ sync::{Arc, Mutex}, }; -use crate::ast::{Diagnostic, FileId, Files, Span, StoredFile}; +use crate::{ + ast::{Diagnostic, FileId, Files, Span, StoredFile}, + Options, VerifyError, +}; -use super::{Server, ServerError}; +use super::{unless_fatal_error, Server, ServerError}; pub struct TestServer { pub files: Arc>, + werr: bool, pub diagnostics: Vec, pub statuses: HashMap, } impl TestServer { - pub fn new() -> Self { + pub fn new(options: &Options) -> Self { TestServer { files: Default::default(), + werr: options.werr, diagnostics: Default::default(), statuses: Default::default(), } @@ -36,8 +41,9 @@ impl Server for TestServer { &self.files } - fn add_diagnostic(&mut self, diagnostic: Diagnostic) -> Result<(), ServerError> { - self.diagnostics.push(diagnostic); + fn add_diagnostic(&mut self, diagnostic: Diagnostic) -> Result<(), VerifyError> { + self.diagnostics + .push(unless_fatal_error(self.werr, diagnostic)?); Ok(()) } From 2d01bc0e1dc95bbfe561e18262ce887937ff1268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Schro=CC=88er?= Date: Sat, 11 May 2024 22:12:50 +0200 Subject: [PATCH 16/25] vscode-ext: refactor the client basic user interactions now working with the new server code. client has been restructured for a simpler and more direct interactions, with necessary reset handling. inline ghost text is not functional yet, and the code also needs to be split into multiple files. --- src/main.rs | 29 +- src/servers/cli.rs | 4 +- src/servers/lsp.rs | 14 +- src/servers/mod.rs | 11 +- src/servers/test.rs | 6 +- vscode-ext/src/APIRegister.ts | 42 -- vscode-ext/src/Configuration.ts | 15 +- vscode-ext/src/Verifier.ts | 440 ++++++++++++++++++ vscode-ext/src/extension.ts | 116 +---- vscode-ext/src/manager/Manager.ts | 72 --- vscode-ext/src/manager/StateManager.ts | 47 -- vscode-ext/src/manager/VerificationManager.ts | 34 -- vscode-ext/src/view/GutterInformationView.ts | 141 ------ vscode-ext/src/view/InlineGhostTextView.ts | 99 ---- vscode-ext/src/view/StatusBarView.ts | 111 ----- vscode-ext/src/view/View.ts | 16 - vscode-ext/src/view/ViewCollection.ts | 31 -- vscode-ext/tsconfig.json | 9 +- 18 files changed, 490 insertions(+), 747 deletions(-) delete mode 100644 vscode-ext/src/APIRegister.ts create mode 100644 vscode-ext/src/Verifier.ts delete mode 100644 vscode-ext/src/manager/Manager.ts delete mode 100644 vscode-ext/src/manager/StateManager.ts delete mode 100644 vscode-ext/src/manager/VerificationManager.ts delete mode 100644 vscode-ext/src/view/GutterInformationView.ts delete mode 100644 vscode-ext/src/view/InlineGhostTextView.ts delete mode 100644 vscode-ext/src/view/StatusBarView.ts delete mode 100644 vscode-ext/src/view/View.ts delete mode 100644 vscode-ext/src/view/ViewCollection.ts diff --git a/src/main.rs b/src/main.rs index 5a2ed0d..d1c4bcb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,7 +27,7 @@ use intrinsic::{annotations::init_calculi, distributions::init_distributions, li use procs::add_default_specs; use proof_rules::init_encodings; use resource_limits::{await_with_resource_limits, LimitError, LimitsRef}; -use servers::{CliServer, LspServer, Server, ServerError}; +use servers::{CliServer, LspServer, Server, ServerError, VerifyResult}; use slicing::init_slicing; use thiserror::Error; use timing::DispatchBuilder; @@ -583,8 +583,9 @@ fn verify_files_main( result.print_prove_result(files_mutex, &vc_expr, &mut translate, name); } let status = match &result.prove_result { - ProveResult::Proof => true, - ProveResult::Counterexample(_) | ProveResult::Unknown(_) => false, + ProveResult::Proof => VerifyResult::Verified, + ProveResult::Counterexample(_) => VerifyResult::Failed, + ProveResult::Unknown(_) => VerifyResult::Unknown, }; server .set_verify_status(verify_unit.span, status) @@ -613,16 +614,18 @@ fn verify_files_main( } } - println!(); - let ending = if num_failures == 0 { - " veni, vidi, vici!" - } else { - "" - }; - println!( - "{} verified, {} failed.{}", - num_proven, num_failures, ending - ); + if !options.language_server { + println!(); + let ending = if num_failures == 0 { + " veni, vidi, vici!" + } else { + "" + }; + println!( + "{} verified, {} failed.{}", + num_proven, num_failures, ending + ); + } Ok(num_failures == 0) } diff --git a/src/servers/cli.rs b/src/servers/cli.rs index 5b93424..f48ea77 100644 --- a/src/servers/cli.rs +++ b/src/servers/cli.rs @@ -9,7 +9,7 @@ use crate::{ Options, VerifyError, }; -use super::{unless_fatal_error, Server, ServerError}; +use super::{unless_fatal_error, Server, ServerError, VerifyResult}; pub struct CliServer { werr: bool, @@ -65,7 +65,7 @@ impl Server for CliServer { Ok(()) } - fn set_verify_status(&mut self, _span: Span, _status: bool) -> Result<(), ServerError> { + fn set_verify_status(&mut self, _span: Span, _status: VerifyResult) -> Result<(), ServerError> { // TODO Ok(()) } diff --git a/src/servers/lsp.rs b/src/servers/lsp.rs index db0a017..63f58f0 100644 --- a/src/servers/lsp.rs +++ b/src/servers/lsp.rs @@ -17,17 +17,17 @@ use crate::{ VerifyError, }; -use super::{Server, ServerError}; +use super::{Server, ServerError, VerifyResult}; #[derive(Debug, Serialize, Deserialize)] -struct VerifyStatusRequest { +struct VerifyRequest { text_document: VersionedTextDocumentIdentifier, } #[derive(Debug, Serialize, Deserialize)] struct VerifyStatusUpdate { document: VersionedTextDocumentIdentifier, - statuses: Vec<(lsp_types::Range, bool)>, + statuses: Vec<(lsp_types::Range, VerifyResult)>, } /// A connection to an LSP client. @@ -36,7 +36,7 @@ pub struct LspServer { files: Arc>, connection: Connection, diagnostics: Vec, - statuses: HashMap, + statuses: HashMap, } impl LspServer { @@ -84,9 +84,9 @@ impl LspServer { for msg in &receiver { match msg { Message::Request(req) => { - if let "custom/verifyStatus" = req.method.as_str() { + if let "custom/verify" = req.method.as_str() { let (id, params) = req - .extract::("custom/verifyStatus") + .extract::("custom/verify") .map_err(|e| VerifyError::ServerError(e.into()))?; self.project_root = Some(params.text_document.clone()); let files = self.files.lock().unwrap(); @@ -252,7 +252,7 @@ impl Server for LspServer { Ok(()) } - fn set_verify_status(&mut self, span: Span, status: bool) -> Result<(), ServerError> { + fn set_verify_status(&mut self, span: Span, status: VerifyResult) -> Result<(), ServerError> { self.statuses.insert(span, status); self.publish_verify_statuses()?; Ok(()) diff --git a/src/servers/mod.rs b/src/servers/mod.rs index 8d416bb..6b16e45 100644 --- a/src/servers/mod.rs +++ b/src/servers/mod.rs @@ -16,11 +16,20 @@ mod test; use ariadne::ReportKind; pub use cli::CliServer; pub use lsp::LspServer; +use serde::{Deserialize, Serialize}; #[cfg(test)] pub use test::TestServer; pub type ServerError = Box; +#[derive(Debug, Serialize, Deserialize, Clone, Copy)] +#[serde(rename_all = "lowercase")] +pub enum VerifyResult { + Verified, + Failed, + Unknown, +} + /// A server that serves information to a client, such as the CLI or an LSP /// client. pub trait Server: Send { @@ -36,7 +45,7 @@ pub trait Server: Send { fn add_diagnostic(&mut self, diagnostic: Diagnostic) -> Result<(), VerifyError>; /// Send a verification status message to the client (a custom notification). - fn set_verify_status(&mut self, span: Span, status: bool) -> Result<(), ServerError>; + fn set_verify_status(&mut self, span: Span, status: VerifyResult) -> Result<(), ServerError>; } fn unless_fatal_error(werr: bool, diagnostic: Diagnostic) -> Result { diff --git a/src/servers/test.rs b/src/servers/test.rs index c4afddd..371aeaa 100644 --- a/src/servers/test.rs +++ b/src/servers/test.rs @@ -8,13 +8,13 @@ use crate::{ Options, VerifyError, }; -use super::{unless_fatal_error, Server, ServerError}; +use super::{unless_fatal_error, Server, ServerError, VerifyResult}; pub struct TestServer { pub files: Arc>, werr: bool, pub diagnostics: Vec, - pub statuses: HashMap, + pub statuses: HashMap, } impl TestServer { @@ -47,7 +47,7 @@ impl Server for TestServer { Ok(()) } - fn set_verify_status(&mut self, span: Span, status: bool) -> Result<(), ServerError> { + fn set_verify_status(&mut self, span: Span, status: VerifyResult) -> Result<(), ServerError> { self.statuses.insert(span, status); Ok(()) } diff --git a/vscode-ext/src/APIRegister.ts b/vscode-ext/src/APIRegister.ts deleted file mode 100644 index 0fab726..0000000 --- a/vscode-ext/src/APIRegister.ts +++ /dev/null @@ -1,42 +0,0 @@ -import * as vscode from 'vscode'; - -export const registerFunctions: { [K: string]: Function } = { - "onDidChangeConfiguration": vscode.workspace.onDidChangeConfiguration, - "onDidChangeTextDocument": vscode.workspace.onDidChangeTextDocument, - "onDidSaveTextDocument": vscode.workspace.onDidSaveTextDocument, -} - -export type RegisterType = keyof typeof registerFunctions; - -export default class APIRegister { - - /// Store all registered callbacks in a map to submit them to vscode api later - private static callbackMap = new Map void>>(); - - - /// Register a callback to be called when the vscode api event is triggered - public static register(type: RegisterType, callback: (...args: any[]) => void): void { - this.callbackMap.has(type) ? this.callbackMap.get(type)?.push(callback) : this.callbackMap.set(type, [callback]); - } - - /// Submit all registered callbacks to vscode api - public static submitAll(): void { - - for (const type of this.callbackMap.keys()) { - if (registerFunctions[type] === undefined) { - throw new Error(`The type ${type} is not a valid registration type`); - } - - // All callbacks that we want to register to the specific event from vscode api - const callbackList = this.callbackMap.get(type)!; - - // Collect all the callbacks into one function - const totalCallback = (...args: any[]) => { callbackList.forEach((callback) => callback(...args)) }; - - // Register the function to the vscode api by calling the corresponding event registration function - registerFunctions[type](totalCallback); - } - - } - -} diff --git a/vscode-ext/src/Configuration.ts b/vscode-ext/src/Configuration.ts index 7fa58a2..f44ef18 100644 --- a/vscode-ext/src/Configuration.ts +++ b/vscode-ext/src/Configuration.ts @@ -4,9 +4,9 @@ export const CONFIGURATION_SECTION = 'caesar'; export default class Configuration { - /// Get a configuration value from the configuration file with the given key + /// Get a configuration value from the configuration file with the given key public static get(key: string): any { - const val: any | undefined = vscode.workspace.getConfiguration(CONFIGURATION_SECTION).get(key) + const val = vscode.workspace.getConfiguration(CONFIGURATION_SECTION).get(key) if (val === undefined) { throw new Error(`${key} is not defined in the configuration file`); } @@ -34,13 +34,12 @@ export class ConfigCategory { return Configuration.get(this.getPath() + "." + key); } - } -// Configurations +// Configurations // ------------------------------------------------ -// Root Configurations: +// Root Configurations: export const ViewConfiguration = new ConfigCategory("uI", null); @@ -50,9 +49,3 @@ export const ViewConfiguration = new ConfigCategory("uI", null); export const GutterInformationViewConfig = new ConfigCategory('gutterIcons', ViewConfiguration,); export const StatusBarViewConfig = new ConfigCategory('statusBar', ViewConfiguration); export const InlineGhostTextViewConfig = new ConfigCategory('inlineGhostText', ViewConfiguration); - - - - - - diff --git a/vscode-ext/src/Verifier.ts b/vscode-ext/src/Verifier.ts new file mode 100644 index 0000000..1e2a984 --- /dev/null +++ b/vscode-ext/src/Verifier.ts @@ -0,0 +1,440 @@ +import { LanguageClientOptions, TextDocumentIdentifier, VersionedTextDocumentIdentifier } from "vscode-languageclient"; +import { LanguageClient, ServerOptions } from "vscode-languageclient/node"; +import { ExtensionContext, Range, StatusBarItem, TextDocument, TextEditorDecorationType } from "vscode"; +import * as vscode from 'vscode'; +import { CONFIGURATION_SECTION, GutterInformationViewConfig, InlineGhostTextViewConfig, StatusBarViewConfig } from "./Configuration"; + +class DocumentMap { + private map: Map = new Map(); + + public insert(document_id: TextDocumentIdentifier, value: T) { + this.map.set(document_id.uri.toString(), [document_id, value]); + } + + public get(document_id: TextDocumentIdentifier): T | undefined { + let res = this.map.get(document_id.uri.toString()); + if (res !== undefined) { + return res[1]; + } + return undefined; + } + + public entries(): Array<[TextDocumentIdentifier, T]> { + return Array.from(this.map.values()); + } +} + +export enum ServerStatus { + Starting, + Ready, + FailedToStart, + Verifying, + Finished, +} + +export enum VerifyResult { + Verified = "verified", + Failed = "failed", + Unknown = "unknown", +} + +export type VerifyStatusNotification = { + document: VersionedTextDocumentIdentifier, + statuses: Array<[vscode.Range, VerifyResult]>, +}; + +export type ComputedPreNotification = { + document: VersionedTextDocumentIdentifier, + pres: Array<[vscode.Range, string]>, +}; + +class CaesarClient { + private client: LanguageClient; + private statusListeners: Array<(status: ServerStatus) => void> = new Array(); + private updateListeners: Array<(document: TextDocumentIdentifier, results: Array<[Range, VerifyResult]>) => void> = new Array(); + private computedPreListeners: Array<(document: TextDocumentIdentifier, results: Array<[Range, string]>) => void> = new Array(); + + constructor(context: ExtensionContext) { + let serverOptions: ServerOptions = { + run: { + command: 'cargo', + args: ['run', '--', '--language-server'], + options: { + }, // TODO!! + }, + debug: { + command: 'cargo', + args: ['run', '--', '--language-server'], + options: { + env: { + ...process.env, + "RUST_LOG": "caesar=info", + "NO_COLOR": "1", + "RUST_BACKTRACE": "1" + } + }, // TODO!! + } + }; + + let clientOptions: LanguageClientOptions = { + diagnosticCollectionName: 'caesar', + documentSelector: [{ scheme: 'file', language: 'heyvl' }], + synchronize: { + // Notify the server about file changes to '.clientrc files contained in the workspace + fileEvents: vscode.workspace.createFileSystemWatcher('**/*.heyvl') + } + }; + + // Create the language client and start the client. + this.client = new LanguageClient( + 'caesar', + 'Caesar', + serverOptions, + clientOptions + ); + context.subscriptions.push(this.client); + + // set up listeners for our custom events + context.subscriptions.push(this.client.onNotification("custom/verifyStatus", (params: VerifyStatusNotification) => { + for (let listener of this.updateListeners) { + listener(params.document, params.statuses); + } + })); + + context.subscriptions.push(this.client.onNotification("custom/computedPre", (params: ComputedPreNotification) => { + for (let listener of this.computedPreListeners) { + listener(params.document, params.pres); + } + })); + + // listen to onDidSaveTextDocument events + context.subscriptions.push(vscode.workspace.onDidSaveTextDocument((document) => { + // TODO: look at setting + this.verify(document); + })); + + // listen to commands + vscode.commands.registerCommand('caesar.restartServer', async () => { + await this.restart(); + }); + + vscode.commands.registerCommand('caesar.startServer', async () => { + await this.start(); + }); + + vscode.commands.registerCommand('caesar.stopServer', async () => { + await this.stop(); + }); + + vscode.commands.registerCommand('caesar.verify', async () => { + let openEditor = vscode.window.activeTextEditor; + if (openEditor) { + this.verify(openEditor.document); + } + }); + } + + async start() { + console.log("Starting Caesar"); + this.notifyStatusUpdate(ServerStatus.Starting); + await this.client.start(); + this.notifyStatusUpdate(ServerStatus.Ready); + } + + async restart() { + console.log("Restarting Caesar"); + this.client.restart(); + } + + async stop() { + console.log("Stopping Caesar"); + this.client.stop(); + } + + async verify(document: TextDocument) { + let documentItem = { + uri: document.uri.toString(), + languageId: document.languageId, + version: document.version, + text: document.getText() + }; + this.notifyStatusUpdate(ServerStatus.Verifying); + await this.client.sendRequest('custom/verify', { text_document: documentItem }); + // TODO: handle errors + this.notifyStatusUpdate(ServerStatus.Finished); + } + + public onStatusUpdate(callback: (status: ServerStatus) => void) { + this.statusListeners.push(callback); + } + + private notifyStatusUpdate(status: ServerStatus) { + for (let listener of this.statusListeners) { + listener(status); + } + } + + public onVerifyResult(callback: (document: TextDocumentIdentifier, results: Array<[Range, VerifyResult]>) => void) { + this.updateListeners.push(callback); + } + + public onComputedPre(callback: (document: TextDocumentIdentifier, results: Array<[Range, string]>) => void) { + this.computedPreListeners.push(callback); + } +} + +export class Verifier { + + public context: ExtensionContext; + public client: CaesarClient; + private statusBar: StatusBarComponent; + private gutterStatus: GutterStatusComponent; + private displayComputedPre: ComputedPreComponent; + + constructor(context: ExtensionContext) { + this.context = context; + this.client = new CaesarClient(context); + this.statusBar = new StatusBarComponent(this); + this.gutterStatus = new GutterStatusComponent(this); + this.displayComputedPre = new ComputedPreComponent(this); + } + + async start() { + await this.client.start(); + } + +} + +class StatusBarComponent { + + private enabled: boolean; + private status: ServerStatus = ServerStatus.Starting; + private view: StatusBarItem; + + constructor(verifier: Verifier) { + // create the view + this.view = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 99); + verifier.context.subscriptions.push(this.view); + this.view.text = "Caesar"; + + this.view.tooltip = new vscode.MarkdownString( + "[Restart Caesar](command:caesar.restartServer)\n\n" + + "[Start Caesar](command:caesar.startServer)\n\n" + + "[Stop Caesar](command:caesar.stopServer)" + , true); + + // render if enabled + this.enabled = StatusBarViewConfig.get("showStatusBar"); + this.render(); + + // subscribe to config changes + verifier.context.subscriptions.push(vscode.workspace.onDidChangeConfiguration((e: vscode.ConfigurationChangeEvent) => { + if (e.affectsConfiguration(CONFIGURATION_SECTION)) { + this.enabled = StatusBarViewConfig.get("showStatusBar"); + this.render(); + } + })); + + // listen to verifier updates + verifier.client.onStatusUpdate((status) => { + this.status = status; + this.render(); + }); + } + + render() { + if (this.enabled) { + switch (this.status) { + case ServerStatus.Starting: + this.view.text = "$(sync~spin) Starting Caesar..."; + break; + case ServerStatus.Ready: + this.view.text = "$(check) Caesar Ready"; + break; + case ServerStatus.Verifying: + this.view.text = "$(sync~spin) Verifying..."; + break; + case ServerStatus.Finished: + this.view.text = "$(check) Verified"; + break; + } + this.view.show(); + } else { + this.view.hide(); + } + } +} + +class GutterStatusComponent { + + private enabled: boolean; + private status: DocumentMap>; + + private verifyDecType: vscode.TextEditorDecorationType; + private failedDecType: vscode.TextEditorDecorationType; + private unknownDecType: vscode.TextEditorDecorationType; + + constructor(verifier: Verifier) { + // create decorations + this.verifyDecType = vscode.window.createTextEditorDecorationType({ gutterIconSize: "contain", gutterIconPath: verifier.context.asAbsolutePath('images/verified.png') }); + this.failedDecType = vscode.window.createTextEditorDecorationType({ gutterIconSize: "contain", gutterIconPath: verifier.context.asAbsolutePath('images/failed.png') }); + this.unknownDecType = vscode.window.createTextEditorDecorationType({ gutterIconSize: "contain", gutterIconPath: verifier.context.asAbsolutePath('images/unknown.png') }); + + // render if enabled + this.enabled = GutterInformationViewConfig.get("showGutterIcons"); + + this.status = new DocumentMap(); + + // subscribe to config changes + verifier.context.subscriptions.push(vscode.workspace.onDidChangeConfiguration((e: vscode.ConfigurationChangeEvent) => { + if (e.affectsConfiguration(CONFIGURATION_SECTION)) { + this.enabled = StatusBarViewConfig.get("showGutterIcons"); + this.render(); + } + })); + + // render when visible editors change + verifier.context.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors((_visibleEditors) => { + this.render(); + })); + + // listen to status and verify updates + verifier.client.onStatusUpdate((status) => { + if (status == ServerStatus.Verifying) { + for (let [_document, results] of this.status.entries()) { + results.length = 0; + } + this.render(); + } + }); + + verifier.client.onVerifyResult((document, results) => { + this.status.insert(document, results); + this.render(); + }); + } + + render() { + for (let [document_id, results] of this.status.entries()) { + for (let editor of vscode.window.visibleTextEditors) { + if (editor.document.uri.toString() !== document_id.uri) { + continue; + } + + let verifiedProcs: vscode.DecorationOptions[] = []; + let failedProcs: vscode.DecorationOptions[] = []; + let unknownProcs: vscode.DecorationOptions[] = []; + + if (this.enabled) { + for (let [range, result] of results) { + let line = range.start.line; + let gutterRange = new vscode.Range(line, 0, line, 0); + switch (result) { + case VerifyResult.Verified: + verifiedProcs.push({ range: gutterRange, hoverMessage: 'Verified' }); + break; + case VerifyResult.Failed: + failedProcs.push({ range: gutterRange, hoverMessage: 'Not Verified' }); + break; + case VerifyResult.Unknown: + unknownProcs.push({ range: gutterRange, hoverMessage: 'Unknown' }); + break; + } + } + } + + editor.setDecorations(this.verifyDecType, verifiedProcs); + editor.setDecorations(this.failedDecType, failedProcs); + editor.setDecorations(this.unknownDecType, unknownProcs); + } + } + } +} + +class ComputedPreComponent { + + private enabled: boolean; + private computedPres: DocumentMap>; + + private decorationType: TextEditorDecorationType; + + constructor(verifier: Verifier) { + // create decoration + this.decorationType = vscode.window.createTextEditorDecorationType({}); + + // set enabled flag + this.enabled = GutterInformationViewConfig.get("showGutterIcons"); + + this.computedPres = new DocumentMap(); + + // subscribe to config changes + verifier.context.subscriptions.push(vscode.workspace.onDidChangeConfiguration((e: vscode.ConfigurationChangeEvent) => { + if (e.affectsConfiguration(CONFIGURATION_SECTION)) { + this.enabled = InlineGhostTextViewConfig.get("showInlineGhostText"); + this.render(); + } + })); + + // render when visible text editors change + verifier.context.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors((_visibleEditors) => { + this.render(); + })); + + // listen to custom/computedPre notifications + verifier.client.onComputedPre((document, pres) => { + this.computedPres.insert(document, pres); + }); + + // clear all information when a new verification task is started + verifier.client.onStatusUpdate((status) => { + if (status == ServerStatus.Verifying) { + for (let [_document, results] of this.computedPres.entries()) { + results.length = 0; + } + this.render(); + } + }); + + // TODO: listen to content changes to remove lines? + } + + render() { + let backgroundColor = new vscode.ThemeColor('caesar.inlineGhostBackgroundColor'); + let color = new vscode.ThemeColor('caesar.inlineGhostForegroundColor'); + + for (let [document_id, pres] of this.computedPres.entries()) { + for (let editor of vscode.window.visibleTextEditors) { + if (editor.document.uri.toString() !== document_id.uri) { + continue; + } + + let decorations: vscode.DecorationOptions[] = []; + + if (this.enabled) { + for (let [range, text] of pres) { + let line = range.start.line; + if (line === 0) { + continue; + } + let lineAbove = line - 1; + let rangeAbove = new vscode.Range(lineAbove, 0, lineAbove, 0); + if (editor.document.lineAt(lineAbove).text.trim() === '') { + decorations.push({ + range: rangeAbove, + renderOptions: { + after: { + backgroundColor, + color, + contentText: text + } + } + }); + } + } + } + + editor.setDecorations(this.decorationType, decorations); + } + } + } +} diff --git a/vscode-ext/src/extension.ts b/vscode-ext/src/extension.ts index da09751..f3786c1 100644 --- a/vscode-ext/src/extension.ts +++ b/vscode-ext/src/extension.ts @@ -1,123 +1,13 @@ // The module 'vscode' contains the VS Code extensibility API // Import the module and reference it with the alias vscode in your code below import * as vscode from 'vscode'; -import * as path from 'path'; -import * as os from 'os'; -import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient/node'; -import { VerificationManager } from './manager/VerificationManager'; -import { GutterInformationView } from './view/GutterInformationView'; -import { StatusBarView } from './view/StatusBarView'; -import { State, StateManager } from './manager/StateManager'; -import { InlineGhostTextView } from './view/InlineGhostTextView'; -import { ViewCollection } from './view/ViewCollection'; -import APIRegister from './APIRegister'; +import { Verifier } from './Verifier'; - -let client: LanguageClient; // This method is called when your extension is activated // Your extension is activated the very first time the command is executed export function activate(context: vscode.ExtensionContext) { - - let serverExecutable = "cargo" - - // If the extension is launched in debug mode then the debug server options are used - // Otherwise the run options are used - let serverOptions: ServerOptions = { - run: { - command: serverExecutable, - args: ['run', '--', '--language-server'], - options: { cwd: path.resolve(os.homedir(), 'caesar') }, - }, - debug: { - command: serverExecutable, - args: ['run', '--', '--language-server'], - options: { cwd: path.resolve(os.homedir(), 'caesar') }, - } - }; - - // Options to control the language client - let clientOptions: LanguageClientOptions = { - diagnosticCollectionName: 'caesar', - // Register the server for heyvl documents - documentSelector: [{ scheme: 'file', language: 'heyvl' }], - synchronize: { - // Notify the server about file changes to '.clientrc files contained in the workspace - fileEvents: vscode.workspace.createFileSystemWatcher('**/*.heyvl') - } - }; - - // Create the language client and start the client. - client = new LanguageClient( - 'caesar', - 'Caesar', - serverOptions, - clientOptions - ); - - - // Initialize Managers - let verificationManager = new VerificationManager(client); - let stateManager = new StateManager(client); - - // // Initialize UI Views - let viewCollection = new ViewCollection(verificationManager, stateManager, context, client); - - APIRegister.register('onDidSaveTextDocument', (textDocument) => { - if (textDocument.languageId === "heyvl") { - if (stateManager.getState() === State.Starting) { - return - } - const openEditor = vscode.window.visibleTextEditors.filter( - editor => editor.document.uri === textDocument.uri - )[0] - stateManager.setState(State.Verifying); - console.log("Verification Started") - - verificationManager.verify(openEditor, textDocument).then((_) => { - stateManager.setState(State.Finished) - }) - } - }); - - - vscode.commands.registerCommand('caesar.restartServer', async () => { - console.log("Restarting Caesar...") - client.restart() - }); - - vscode.commands.registerCommand('caesar.startServer', async () => { - console.log("Starting Caesar...") - client.start() - }); - - vscode.commands.registerCommand('caesar.stopServer', async () => { - console.log("Stopping Caesar...") - client.stop() - }); - - vscode.commands.registerCommand('caesar.verify', async () => { - const openEditor = vscode.window.activeTextEditor - if (openEditor) { - stateManager.setState(State.Verifying); - console.log("Verification Started") - verificationManager.verify(openEditor, openEditor.document).then((_) => { - stateManager.setState(State.Finished) - }) - } - }); - - - // Submit all received callbacks to vscode api - APIRegister.submitAll(); - // Start the client. This will also launch the server - client.start(); - - console.log('Caesar is now active!'); - - // Add to a list of disposables which are disposed when this extension is deactivated. - context.subscriptions.push(viewCollection); - context.subscriptions.push(client); - + let verifier = new Verifier(context); + verifier.start(); } // This method is called when the extension is deactivated diff --git a/vscode-ext/src/manager/Manager.ts b/vscode-ext/src/manager/Manager.ts deleted file mode 100644 index 2f81de8..0000000 --- a/vscode-ext/src/manager/Manager.ts +++ /dev/null @@ -1,72 +0,0 @@ -// Parent class for Observer-pattern Subjects which we call Managers -export class Manager { - // Observer-pattern subject - - private observers: Observer[] = [] - - - /// Notify the observers with the latest verification status - public notify(update: any) { - this.observers.forEach(observer => observer.receiveUpdate(update)); - } - - /// Subscribe an observer to the VerificationManager - public subscribe(o: Observer) { - if (this.observers.includes(o)) { - return; - } - this.observers.push(o); - } - - /// Subscribe multiple observers to the VerificationManager - public subscribeMany(o: Array) { - o.forEach(observer => this.subscribe(observer)); - } - - /// Unsubscribe an observer from the VerificationManager - public unsubscribe(o: Observer) { - const index = this.observers.indexOf(o); - if (index === -1) { - return; - } - this.observers.splice(index, 1); - } -} - - -export class Observer { - - private callback: (update: any) => void; - private manager: Manager; - private enabled: boolean = true; - - public constructor(manager: Manager, callback: (update: any) => void) { - this.callback = callback; - this.manager = manager; - - this.manager.subscribe(this); - } - - - public receiveUpdate(update: any): void { - this.callback(update); - } - - public disable() { - if (!this.enabled) { - return; - } - this.manager.unsubscribe(this); - } - - public enable() { - if (this.enabled) { - return; - } - this.manager.subscribe(this); - } -} - - - - diff --git a/vscode-ext/src/manager/StateManager.ts b/vscode-ext/src/manager/StateManager.ts deleted file mode 100644 index 2eacdfe..0000000 --- a/vscode-ext/src/manager/StateManager.ts +++ /dev/null @@ -1,47 +0,0 @@ - -import * as vscode from "vscode"; -import { LanguageClient } from "vscode-languageclient/node"; -import { Manager, Observer } from "./Manager"; - - -export enum State { - Starting, - Ready, - FailedToStart, - Verifying, - Finished, -} - - -// Subject -export class StateManager extends Manager { - - private client: LanguageClient; - - private state: State; - - constructor(client: LanguageClient) { - super(); - this.client = client; - this.state = State.Starting; - this.notify(this.state); - - client.onNotification("custom/serverReady", () => { - this.setState(State.Ready); - }) - } - - - public setState(state: State) { - this.state = state; - this.notify(state); - } - - public getState(): State { - return this.state; - } - -} - - - diff --git a/vscode-ext/src/manager/VerificationManager.ts b/vscode-ext/src/manager/VerificationManager.ts deleted file mode 100644 index 2c10bf5..0000000 --- a/vscode-ext/src/manager/VerificationManager.ts +++ /dev/null @@ -1,34 +0,0 @@ - -import * as vscode from "vscode"; -import { LanguageClient, VersionedTextDocumentIdentifier } from "vscode-languageclient/node"; -import { Manager, Observer } from "./Manager"; -import APIRegister from "../APIRegister"; - - -export type VerificationStatus = { - document: VersionedTextDocumentIdentifier, - statuses: Array<[vscode.Range, boolean]>, -}; - -export class VerificationManager extends Manager { - - private client: LanguageClient; - - - constructor(client: LanguageClient) { - super(); - this.client = client; - } - - public async verify(editor: vscode.TextEditor, document: vscode.TextDocument): Promise { - let documentItem = { - uri: document.uri.toString(), - languageId: document.languageId, - version: document.version, - text: document.getText() - } - await this.client.sendRequest('custom/verifyStatus', { text_document: documentItem }); - } - -} - diff --git a/vscode-ext/src/view/GutterInformationView.ts b/vscode-ext/src/view/GutterInformationView.ts deleted file mode 100644 index 1ada0f8..0000000 --- a/vscode-ext/src/view/GutterInformationView.ts +++ /dev/null @@ -1,141 +0,0 @@ - -import * as vscode from "vscode"; -import { VerificationManager, VerificationStatus } from "../manager/VerificationManager"; -import { Manager, Observer } from "../manager/Manager"; -import Configuration, { CONFIGURATION_SECTION, ConfigCategory, GutterInformationViewConfig } from "../Configuration"; -import APIRegister from "../APIRegister"; -import { EditorView } from "./View"; -import { VersionedTextDocumentIdentifier } from "vscode-languageclient"; -import { LanguageClient } from "vscode-languageclient/node"; - - - -export enum VerifyStatus { - Verified, - Failed, - Unknown -} - -export enum VerificationColors { - Verified = '#66f542', - Failed = '#f23a3a', - Unknown = '#f7aa57' -} - - -/// The view that displays the verification status of individual (co)procedures in the gutter of the editor with corresponding icons -export class GutterInformationView extends EditorView { - private enabled: boolean; - private verificationObserver: Observer; - - private verifyDecType: vscode.TextEditorDecorationType; - private failedDecType: vscode.TextEditorDecorationType; - private unknownDecType: vscode.TextEditorDecorationType; - - private procStatus?: VerificationStatus; - - constructor(verificationManager: VerificationManager, context: vscode.ExtensionContext, client: LanguageClient) { - super(); - - this.enabled = GutterInformationViewConfig.get("showGutterIcons"); - - this.verifyDecType = vscode.window.createTextEditorDecorationType({ gutterIconSize: "contain", gutterIconPath: context.asAbsolutePath('images/verified.png') }); - this.failedDecType = vscode.window.createTextEditorDecorationType({ gutterIconSize: "contain", gutterIconPath: context.asAbsolutePath('images/failed.png') }); - this.unknownDecType = vscode.window.createTextEditorDecorationType({ gutterIconSize: "contain", gutterIconPath: context.asAbsolutePath('images/unknown.png') }); - - this.verificationObserver = new Observer(verificationManager, (update: VerificationStatus) => { this.receiveVerificationUpdate(update) }); - - // Register the configuration change listener - APIRegister.register("onDidChangeConfiguration", (e: vscode.ConfigurationChangeEvent) => { - if (e.affectsConfiguration(CONFIGURATION_SECTION)) { - console.log("Gutter Config Changed") - if (GutterInformationViewConfig.get("showGutterIcons")) { - this.enable(); - } else { - this.disable(); - } - } - }); - - client.onNotification("custom/verifyStatus", (params: VerificationStatus) => { - this.receiveVerificationUpdate(params); - }) - } - - /// Enable the GutterInformationView - public enable() { - if (this.enabled) { - return; - } - this.enabled = true; - this.verificationObserver.enable(); - this.updateView(vscode.window.activeTextEditor!) - } - - /// Disable the GutterInformationView - public disable() { - if (!this.enabled) { - return; - } - this.enabled = false; - this.verificationObserver.disable(); - this.clearVisibleEditors() - } - - /// Callback function for when the VerificationManager updates - private receiveVerificationUpdate(newStatus: VerificationStatus) { - // Update the decorations - const editor = vscode.window.activeTextEditor; - if (editor) { - this.procStatus = newStatus; - this.updateView(editor); - } - } - - - /// Clear the checkmarks from the given editor - public clearView(editor: vscode.TextEditor) { - editor.setDecorations(this.verifyDecType, []); - editor.setDecorations(this.failedDecType, []); - editor.setDecorations(this.unknownDecType, []); - } - - /// Update the checkmarks based on the latest verification status received from the VerificationManager - public updateView(editor: vscode.TextEditor) { - const verifiedProcs: vscode.DecorationOptions[] = []; - const failedProcs: vscode.DecorationOptions[] = []; - const unknownProcs: vscode.DecorationOptions[] = []; - if (this.enabled && this.procStatus != null && this.procStatus.document.uri == editor.document.uri.toString()) { - for (const proc of this.procStatus.statuses) { - const verified = proc[1]; - - const line = proc[0].start.line; - const range = new vscode.Range(line, 0, line, 0); - if (verified) { - // Put the checkmark before the proc. - verifiedProcs.push({ range, hoverMessage: 'Verified' }); - } else { - // Put the X before the proc. - failedProcs.push({ range, hoverMessage: 'Not Verified' }); - } - } - } - editor.setDecorations(this.verifyDecType, verifiedProcs); - editor.setDecorations(this.failedDecType, failedProcs); - editor.setDecorations(this.unknownDecType, unknownProcs); - } - - - /// Dispose of the GutterInformationView - public dispose() { - this.clearVisibleEditors(); - this.verificationObserver.disable(); - this.verifyDecType.dispose(); - this.failedDecType.dispose(); - this.unknownDecType.dispose(); - } - -} - - - diff --git a/vscode-ext/src/view/InlineGhostTextView.ts b/vscode-ext/src/view/InlineGhostTextView.ts deleted file mode 100644 index 6f6b7fd..0000000 --- a/vscode-ext/src/view/InlineGhostTextView.ts +++ /dev/null @@ -1,99 +0,0 @@ -import * as vscode from "vscode"; -import { Observer } from "../manager/Manager"; -import { VerificationManager, VerificationStatus } from "../manager/VerificationManager"; -import APIRegister from "../APIRegister"; -import { CONFIGURATION_SECTION, InlineGhostTextViewConfig } from "../Configuration"; -import { EditorView } from "./View"; - - -/// The view that shows the wp/wrt/ert of the respective lines as ghost text in the editor -export class InlineGhostTextView extends EditorView { - - private verificationObserver: Observer; - - - private lineTextMap: Map = new Map([[1, "test"], [2, "test2"], [3, "test3"]]); - - private decorationType: vscode.TextEditorDecorationType; - - constructor(verificationManager: VerificationManager) { - super(); - this.verificationObserver = new Observer(verificationManager, (update: VerificationStatus) => { this.receiveVerificationUpdate(update) }); - this.decorationType = vscode.window.createTextEditorDecorationType({}); - - - APIRegister.register("onDidChangeConfiguration", (e: vscode.ConfigurationChangeEvent) => { - if (e.affectsConfiguration(CONFIGURATION_SECTION)) { - if (InlineGhostTextViewConfig.get("showInlineGhostText")) { - this.enable(); - } else { - this.disable(); - } - } - }); - - } - - public enable() { - this.verificationObserver.enable(); - this.updateView(vscode.window.activeTextEditor!); - } - - public disable() { - this.verificationObserver.disable(); - this.clearVisibleEditors(); - } - - private receiveVerificationUpdate(newStatus: VerificationStatus) { - // Update the decorations - const editor = vscode.window.activeTextEditor; - if (editor) { - this.updateView(editor); - } - } - - public updateText(line: number, text: string) { - this.lineTextMap.set(line, text); - } - - public clearView(editor: vscode.TextEditor) { - editor.setDecorations(this.decorationType, []); - } - - public updateView(editor: vscode.TextEditor) { - const decorations: vscode.DecorationOptions[] = []; - - this.lineTextMap.forEach((text, line) => { - if (this.checkEmptyLine(Math.max(0, line - 1))) { - const range = new vscode.Range(Math.max(0, line - 1), 0, Math.max(0, line - 1), 0); - decorations.push({ - range, renderOptions: { - after: { - backgroundColor: new vscode.ThemeColor('caesar.inlineGhostBackgroundColor'), - color: new vscode.ThemeColor('caesar.inlineGhostForegroundColor'), - contentText: text - } - } - }); - } - }); - - editor.setDecorations(this.decorationType, decorations); - } - - public checkEmptyLine(line: number): boolean { - // Checks if the line above the given line number is empty - const textEditor = vscode.window.activeTextEditor; - if (textEditor && textEditor.document.lineCount > line) { - const lineText = textEditor.document.lineAt(line).text; - return lineText.trim() === ''; - } - return false; - } - - public dispose() { - this.clearVisibleEditors(); - this.decorationType.dispose(); - } - -} diff --git a/vscode-ext/src/view/StatusBarView.ts b/vscode-ext/src/view/StatusBarView.ts deleted file mode 100644 index 3b8d83f..0000000 --- a/vscode-ext/src/view/StatusBarView.ts +++ /dev/null @@ -1,111 +0,0 @@ -import * as vscode from "vscode"; -import { VerificationStatus } from "../manager/VerificationManager"; -import { Manager, Observer } from "../manager/Manager"; -import { State, StateManager } from "../manager/StateManager"; -import APIRegister from "../APIRegister"; -import { CONFIGURATION_SECTION, StatusBarViewConfig } from "../Configuration"; - - - - - - -/// The view for the status bar at the bottom of the editor -export class StatusBarView { - - private stateObserver: Observer; - - private statusBarItems: Array; - private progressText: vscode.StatusBarItem; - - constructor(stateManager: StateManager) { - - this.stateObserver = new Observer(stateManager, (update: State) => { this.receiveStateUpdate(update) }); - - this.statusBarItems = []; - - this.progressText = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 99); - this.progressText.text = "caesar"; - - - this.progressText.tooltip = new vscode.MarkdownString( - "[Restart Caesar](command:caesar.restartServer)\n\n" + - "[Start Caesar](command:caesar.startServer)\n\n" + - "[Stop Caesar](command:caesar.stopServer)" - , true); - - this.statusBarItems.push(this.progressText); - - this.showStatusBar(); - - APIRegister.register("onDidChangeConfiguration", (e: vscode.ConfigurationChangeEvent) => { - if (e.affectsConfiguration(CONFIGURATION_SECTION)) { - if (StatusBarViewConfig.get("showStatusBar")) { - this.enable(); - } else { - this.disable(); - } - } - }); - - } - - private showStatusBar() { - for (const statusBarItem of this.statusBarItems) { - statusBarItem.show(); - } - } - - private hideStatusBar() { - for (const statusBarItem of this.statusBarItems) { - statusBarItem.hide(); - } - } - - /// Disable the status bar by hiding it and disabling the observer - public disable() { - this.hideStatusBar(); - this.stateObserver.disable(); - } - - /// Enable the status bar by showing it and enabling the observer - public enable() { - this.showStatusBar(); - this.stateObserver.enable(); - } - - /// Dispose of the status bar - public dispose() { - for (const statusBarItem of this.statusBarItems) { - statusBarItem.dispose(); - } - this.stateObserver.disable(); - } - - /// Update the status bar text based on the latest state received from the StateManager - private receiveStateUpdate(p: State) { - switch (p) { - case State.Starting: - this.progressText.text = StatusBarText.Starting; - break; - case State.Ready: - this.progressText.text = StatusBarText.Ready; - break; - case State.Verifying: - this.progressText.text = StatusBarText.Verifying; - break; - case State.Finished: - this.progressText.text = StatusBarText.Verified; - break; - } - } - -} - - -export enum StatusBarText { - Starting = "$(sync~spin) Starting Caesar...", - Ready = "$(check) Caesar Ready", - Verifying = "$(sync~spin) Verifying...", - Verified = "$(check) Verified" -} diff --git a/vscode-ext/src/view/View.ts b/vscode-ext/src/view/View.ts deleted file mode 100644 index fd72df8..0000000 --- a/vscode-ext/src/view/View.ts +++ /dev/null @@ -1,16 +0,0 @@ -import * as vscode from 'vscode'; - -export abstract class EditorView { - - public abstract updateView(update: any): void; - - public abstract clearView(editor: vscode.TextEditor): void; - - public abstract dispose(): void; - - public clearVisibleEditors() { - const editors = vscode.window.visibleTextEditors; - editors.forEach(editor => this.clearView(editor)); - } - -} diff --git a/vscode-ext/src/view/ViewCollection.ts b/vscode-ext/src/view/ViewCollection.ts deleted file mode 100644 index 1902d04..0000000 --- a/vscode-ext/src/view/ViewCollection.ts +++ /dev/null @@ -1,31 +0,0 @@ -import * as vscode from "vscode"; - -import { StateManager } from "../manager/StateManager"; -import { VerificationManager } from "../manager/VerificationManager"; -import { GutterInformationView } from "./GutterInformationView"; -import { InlineGhostTextView } from "./InlineGhostTextView"; -import { StatusBarView } from "./StatusBarView"; -import { LanguageClient } from "vscode-languageclient/node"; - - -/// A container for all the views in the extension -/// Manages the creation and the on/off configurations of the views -export class ViewCollection { - public gutterInfo: GutterInformationView | null; - public statusBar: StatusBarView | null; - public inlineGhostText: InlineGhostTextView | null; - - - constructor(verificationManager: VerificationManager, stateManager: StateManager, context: vscode.ExtensionContext, client: LanguageClient) { - this.gutterInfo = new GutterInformationView(verificationManager, context, client); - this.statusBar = new StatusBarView(stateManager); - this.inlineGhostText = new InlineGhostTextView(verificationManager); - } - - public dispose() { - this.gutterInfo?.dispose(); - this.statusBar?.dispose(); - this.inlineGhostText?.dispose(); - } - -} diff --git a/vscode-ext/tsconfig.json b/vscode-ext/tsconfig.json index 6954702..f959226 100644 --- a/vscode-ext/tsconfig.json +++ b/vscode-ext/tsconfig.json @@ -8,10 +8,11 @@ ], "sourceMap": true, "rootDir": "src", - "strict": true /* enable all strict type-checking options */ + "strict": true, /* enable all strict type-checking options */ /* Additional Checks */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ + "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + "noUnusedParameters": true, /* Report errors on unused parameters. */ + } } From f50e99a303cfa5ab60bfd61d39c8cc02155d9746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Schro=CC=88er?= Date: Sat, 11 May 2024 22:36:11 +0200 Subject: [PATCH 17/25] vscode-ext: split into multiple files --- vscode-ext/src/CaesarClient.ts | 166 ++++++++++ vscode-ext/src/ComputedPreComponent.ts | 93 ++++++ vscode-ext/src/GutterStatusComponent.ts | 91 ++++++ vscode-ext/src/StatusBarComponent.ts | 65 ++++ vscode-ext/src/Verifier.ts | 408 +----------------------- 5 files changed, 423 insertions(+), 400 deletions(-) create mode 100644 vscode-ext/src/CaesarClient.ts create mode 100644 vscode-ext/src/ComputedPreComponent.ts create mode 100644 vscode-ext/src/GutterStatusComponent.ts create mode 100644 vscode-ext/src/StatusBarComponent.ts diff --git a/vscode-ext/src/CaesarClient.ts b/vscode-ext/src/CaesarClient.ts new file mode 100644 index 0000000..946111a --- /dev/null +++ b/vscode-ext/src/CaesarClient.ts @@ -0,0 +1,166 @@ +import { LanguageClientOptions, TextDocumentIdentifier, VersionedTextDocumentIdentifier } from "vscode-languageclient"; +import { LanguageClient, ServerOptions } from "vscode-languageclient/node"; +import { ExtensionContext, Range, TextDocument } from "vscode"; +import * as vscode from "vscode"; + +export enum ServerStatus { + Starting, + Ready, + FailedToStart, + Verifying, + Finished +} + +export enum VerifyResult { + Verified = "verified", + Failed = "failed", + Unknown = "unknown" +} + +export type VerifyStatusNotification = { + document: VersionedTextDocumentIdentifier; + statuses: Array<[vscode.Range, VerifyResult]>; +}; + +export type ComputedPreNotification = { + document: VersionedTextDocumentIdentifier; + pres: Array<[vscode.Range, string]>; +}; + + +export class CaesarClient { + private client: LanguageClient; + private statusListeners: Array<(status: ServerStatus) => void> = new Array(); + private updateListeners: Array<(document: TextDocumentIdentifier, results: Array<[Range, VerifyResult]>) => void> = new Array(); + private computedPreListeners: Array<(document: TextDocumentIdentifier, results: Array<[Range, string]>) => void> = new Array(); + + constructor(context: ExtensionContext) { + let serverOptions: ServerOptions = { + run: { + command: 'cargo', + args: ['run', '--', '--language-server'], + options: { + + }, // TODO!! + }, + debug: { + command: 'cargo', + args: ['run', '--', '--language-server'], + options: { + + env: { + ...process.env, + "RUST_LOG": "caesar=info", + "NO_COLOR": "1", + "RUST_BACKTRACE": "1" + } + }, // TODO!! + } + }; + + let clientOptions: LanguageClientOptions = { + diagnosticCollectionName: 'caesar', + documentSelector: [{ scheme: 'file', language: 'heyvl' }], + synchronize: { + // Notify the server about file changes to '.clientrc files contained in the workspace + fileEvents: vscode.workspace.createFileSystemWatcher('**/*.heyvl') + } + }; + + // Create the language client and start the client. + this.client = new LanguageClient( + 'caesar', + 'Caesar', + serverOptions, + clientOptions + ); + context.subscriptions.push(this.client); + + // set up listeners for our custom events + context.subscriptions.push(this.client.onNotification("custom/verifyStatus", (params: VerifyStatusNotification) => { + for (let listener of this.updateListeners) { + listener(params.document, params.statuses); + } + })); + + context.subscriptions.push(this.client.onNotification("custom/computedPre", (params: ComputedPreNotification) => { + for (let listener of this.computedPreListeners) { + listener(params.document, params.pres); + } + })); + + // listen to onDidSaveTextDocument events + context.subscriptions.push(vscode.workspace.onDidSaveTextDocument((document) => { + // TODO: look at setting + this.verify(document); + })); + + // listen to commands + vscode.commands.registerCommand('caesar.restartServer', async () => { + await this.restart(); + }); + + vscode.commands.registerCommand('caesar.startServer', async () => { + await this.start(); + }); + + vscode.commands.registerCommand('caesar.stopServer', async () => { + await this.stop(); + }); + + vscode.commands.registerCommand('caesar.verify', async () => { + let openEditor = vscode.window.activeTextEditor; + if (openEditor) { + this.verify(openEditor.document); + } + }); + } + + async start() { + console.log("Starting Caesar"); + this.notifyStatusUpdate(ServerStatus.Starting); + await this.client.start(); + this.notifyStatusUpdate(ServerStatus.Ready); + } + + async restart() { + console.log("Restarting Caesar"); + this.client.restart(); + } + + async stop() { + console.log("Stopping Caesar"); + this.client.stop(); + } + + async verify(document: TextDocument) { + let documentItem = { + uri: document.uri.toString(), + languageId: document.languageId, + version: document.version, + text: document.getText() + }; + this.notifyStatusUpdate(ServerStatus.Verifying); + await this.client.sendRequest('custom/verify', { text_document: documentItem }); + // TODO: handle errors + this.notifyStatusUpdate(ServerStatus.Finished); + } + + public onStatusUpdate(callback: (status: ServerStatus) => void) { + this.statusListeners.push(callback); + } + + private notifyStatusUpdate(status: ServerStatus) { + for (let listener of this.statusListeners) { + listener(status); + } + } + + public onVerifyResult(callback: (document: TextDocumentIdentifier, results: Array<[Range, VerifyResult]>) => void) { + this.updateListeners.push(callback); + } + + public onComputedPre(callback: (document: TextDocumentIdentifier, results: Array<[Range, string]>) => void) { + this.computedPreListeners.push(callback); + } +} \ No newline at end of file diff --git a/vscode-ext/src/ComputedPreComponent.ts b/vscode-ext/src/ComputedPreComponent.ts new file mode 100644 index 0000000..a1a70d2 --- /dev/null +++ b/vscode-ext/src/ComputedPreComponent.ts @@ -0,0 +1,93 @@ +import { Range, TextEditorDecorationType } from "vscode"; +import * as vscode from 'vscode'; +import { CONFIGURATION_SECTION, GutterInformationViewConfig, InlineGhostTextViewConfig } from "./Configuration"; +import { ServerStatus } from "./CaesarClient"; +import { DocumentMap, Verifier } from "./Verifier"; + +export class ComputedPreComponent { + + private enabled: boolean; + private computedPres: DocumentMap>; + + private decorationType: TextEditorDecorationType; + + constructor(verifier: Verifier) { + // create decoration + this.decorationType = vscode.window.createTextEditorDecorationType({}); + + // set enabled flag + this.enabled = GutterInformationViewConfig.get("showGutterIcons"); + + this.computedPres = new DocumentMap(); + + // subscribe to config changes + verifier.context.subscriptions.push(vscode.workspace.onDidChangeConfiguration((e: vscode.ConfigurationChangeEvent) => { + if (e.affectsConfiguration(CONFIGURATION_SECTION)) { + this.enabled = InlineGhostTextViewConfig.get("showInlineGhostText"); + this.render(); + } + })); + + // render when visible text editors change + verifier.context.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors((_visibleEditors) => { + this.render(); + })); + + // listen to custom/computedPre notifications + verifier.client.onComputedPre((document, pres) => { + this.computedPres.insert(document, pres); + }); + + // clear all information when a new verification task is started + verifier.client.onStatusUpdate((status) => { + if (status == ServerStatus.Verifying) { + for (let [_document, results] of this.computedPres.entries()) { + results.length = 0; + } + this.render(); + } + }); + + // TODO: listen to content changes to remove lines? + } + + render() { + let backgroundColor = new vscode.ThemeColor('caesar.inlineGhostBackgroundColor'); + let color = new vscode.ThemeColor('caesar.inlineGhostForegroundColor'); + + for (let [document_id, pres] of this.computedPres.entries()) { + for (let editor of vscode.window.visibleTextEditors) { + if (editor.document.uri.toString() !== document_id.uri) { + continue; + } + + let decorations: vscode.DecorationOptions[] = []; + + if (this.enabled) { + for (let [range, text] of pres) { + let line = range.start.line; + if (line === 0) { + continue; + } + let lineAbove = line - 1; + let rangeAbove = new vscode.Range(lineAbove, 0, lineAbove, 0); + if (editor.document.lineAt(lineAbove).text.trim() === '') { + decorations.push({ + range: rangeAbove, + renderOptions: { + after: { + backgroundColor, + color, + contentText: text + } + } + }); + } + } + } + + editor.setDecorations(this.decorationType, decorations); + } + } + } +} diff --git a/vscode-ext/src/GutterStatusComponent.ts b/vscode-ext/src/GutterStatusComponent.ts new file mode 100644 index 0000000..7591c7e --- /dev/null +++ b/vscode-ext/src/GutterStatusComponent.ts @@ -0,0 +1,91 @@ +import { Range } from "vscode"; +import * as vscode from 'vscode'; +import { CONFIGURATION_SECTION, GutterInformationViewConfig, StatusBarViewConfig } from "./Configuration"; +import { ServerStatus, VerifyResult } from "./CaesarClient"; +import { DocumentMap, Verifier } from "./Verifier"; + +export class GutterStatusComponent { + + private enabled: boolean; + private status: DocumentMap>; + + private verifyDecType: vscode.TextEditorDecorationType; + private failedDecType: vscode.TextEditorDecorationType; + private unknownDecType: vscode.TextEditorDecorationType; + + constructor(verifier: Verifier) { + // create decorations + this.verifyDecType = vscode.window.createTextEditorDecorationType({ gutterIconSize: "contain", gutterIconPath: verifier.context.asAbsolutePath('images/verified.png') }); + this.failedDecType = vscode.window.createTextEditorDecorationType({ gutterIconSize: "contain", gutterIconPath: verifier.context.asAbsolutePath('images/failed.png') }); + this.unknownDecType = vscode.window.createTextEditorDecorationType({ gutterIconSize: "contain", gutterIconPath: verifier.context.asAbsolutePath('images/unknown.png') }); + + // render if enabled + this.enabled = GutterInformationViewConfig.get("showGutterIcons"); + + this.status = new DocumentMap(); + + // subscribe to config changes + verifier.context.subscriptions.push(vscode.workspace.onDidChangeConfiguration((e: vscode.ConfigurationChangeEvent) => { + if (e.affectsConfiguration(CONFIGURATION_SECTION)) { + this.enabled = StatusBarViewConfig.get("showGutterIcons"); + this.render(); + } + })); + + // render when visible editors change + verifier.context.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors((_visibleEditors) => { + this.render(); + })); + + // listen to status and verify updates + verifier.client.onStatusUpdate((status) => { + if (status == ServerStatus.Verifying) { + for (let [_document, results] of this.status.entries()) { + results.length = 0; + } + this.render(); + } + }); + + verifier.client.onVerifyResult((document, results) => { + this.status.insert(document, results); + this.render(); + }); + } + + render() { + for (let [document_id, results] of this.status.entries()) { + for (let editor of vscode.window.visibleTextEditors) { + if (editor.document.uri.toString() !== document_id.uri) { + continue; + } + + let verifiedProcs: vscode.DecorationOptions[] = []; + let failedProcs: vscode.DecorationOptions[] = []; + let unknownProcs: vscode.DecorationOptions[] = []; + + if (this.enabled) { + for (let [range, result] of results) { + let line = range.start.line; + let gutterRange = new vscode.Range(line, 0, line, 0); + switch (result) { + case VerifyResult.Verified: + verifiedProcs.push({ range: gutterRange, hoverMessage: 'Verified' }); + break; + case VerifyResult.Failed: + failedProcs.push({ range: gutterRange, hoverMessage: 'Not Verified' }); + break; + case VerifyResult.Unknown: + unknownProcs.push({ range: gutterRange, hoverMessage: 'Unknown' }); + break; + } + } + } + + editor.setDecorations(this.verifyDecType, verifiedProcs); + editor.setDecorations(this.failedDecType, failedProcs); + editor.setDecorations(this.unknownDecType, unknownProcs); + } + } + } +} diff --git a/vscode-ext/src/StatusBarComponent.ts b/vscode-ext/src/StatusBarComponent.ts new file mode 100644 index 0000000..1376b9f --- /dev/null +++ b/vscode-ext/src/StatusBarComponent.ts @@ -0,0 +1,65 @@ +import { StatusBarItem } from "vscode"; +import * as vscode from 'vscode'; +import { CONFIGURATION_SECTION, StatusBarViewConfig } from "./Configuration"; +import { ServerStatus } from "./CaesarClient"; +import { Verifier } from "./Verifier"; + +export class StatusBarComponent { + + private enabled: boolean; + private status: ServerStatus = ServerStatus.Starting; + private view: StatusBarItem; + + constructor(verifier: Verifier) { + // create the view + this.view = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 99); + verifier.context.subscriptions.push(this.view); + this.view.text = "Caesar"; + + this.view.tooltip = new vscode.MarkdownString( + "[Restart Caesar](command:caesar.restartServer)\n\n" + + "[Start Caesar](command:caesar.startServer)\n\n" + + "[Stop Caesar](command:caesar.stopServer)", + true); + + // render if enabled + this.enabled = StatusBarViewConfig.get("showStatusBar"); + this.render(); + + // subscribe to config changes + verifier.context.subscriptions.push(vscode.workspace.onDidChangeConfiguration((e: vscode.ConfigurationChangeEvent) => { + if (e.affectsConfiguration(CONFIGURATION_SECTION)) { + this.enabled = StatusBarViewConfig.get("showStatusBar"); + this.render(); + } + })); + + // listen to verifier updates + verifier.client.onStatusUpdate((status) => { + this.status = status; + this.render(); + }); + } + + render() { + if (this.enabled) { + switch (this.status) { + case ServerStatus.Starting: + this.view.text = "$(sync~spin) Starting Caesar..."; + break; + case ServerStatus.Ready: + this.view.text = "$(check) Caesar Ready"; + break; + case ServerStatus.Verifying: + this.view.text = "$(sync~spin) Verifying..."; + break; + case ServerStatus.Finished: + this.view.text = "$(check) Verified"; + break; + } + this.view.show(); + } else { + this.view.hide(); + } + } +} diff --git a/vscode-ext/src/Verifier.ts b/vscode-ext/src/Verifier.ts index 1e2a984..a5ac26a 100644 --- a/vscode-ext/src/Verifier.ts +++ b/vscode-ext/src/Verifier.ts @@ -1,10 +1,11 @@ -import { LanguageClientOptions, TextDocumentIdentifier, VersionedTextDocumentIdentifier } from "vscode-languageclient"; -import { LanguageClient, ServerOptions } from "vscode-languageclient/node"; -import { ExtensionContext, Range, StatusBarItem, TextDocument, TextEditorDecorationType } from "vscode"; -import * as vscode from 'vscode'; -import { CONFIGURATION_SECTION, GutterInformationViewConfig, InlineGhostTextViewConfig, StatusBarViewConfig } from "./Configuration"; - -class DocumentMap { +import { TextDocumentIdentifier } from "vscode-languageclient"; +import { ExtensionContext } from "vscode"; +import { CaesarClient } from "./CaesarClient"; +import { StatusBarComponent } from "./StatusBarComponent"; +import { GutterStatusComponent } from "./GutterStatusComponent"; +import { ComputedPreComponent } from "./ComputedPreComponent"; + +export class DocumentMap { private map: Map = new Map(); public insert(document_id: TextDocumentIdentifier, value: T) { @@ -24,165 +25,6 @@ class DocumentMap { } } -export enum ServerStatus { - Starting, - Ready, - FailedToStart, - Verifying, - Finished, -} - -export enum VerifyResult { - Verified = "verified", - Failed = "failed", - Unknown = "unknown", -} - -export type VerifyStatusNotification = { - document: VersionedTextDocumentIdentifier, - statuses: Array<[vscode.Range, VerifyResult]>, -}; - -export type ComputedPreNotification = { - document: VersionedTextDocumentIdentifier, - pres: Array<[vscode.Range, string]>, -}; - -class CaesarClient { - private client: LanguageClient; - private statusListeners: Array<(status: ServerStatus) => void> = new Array(); - private updateListeners: Array<(document: TextDocumentIdentifier, results: Array<[Range, VerifyResult]>) => void> = new Array(); - private computedPreListeners: Array<(document: TextDocumentIdentifier, results: Array<[Range, string]>) => void> = new Array(); - - constructor(context: ExtensionContext) { - let serverOptions: ServerOptions = { - run: { - command: 'cargo', - args: ['run', '--', '--language-server'], - options: { - }, // TODO!! - }, - debug: { - command: 'cargo', - args: ['run', '--', '--language-server'], - options: { - env: { - ...process.env, - "RUST_LOG": "caesar=info", - "NO_COLOR": "1", - "RUST_BACKTRACE": "1" - } - }, // TODO!! - } - }; - - let clientOptions: LanguageClientOptions = { - diagnosticCollectionName: 'caesar', - documentSelector: [{ scheme: 'file', language: 'heyvl' }], - synchronize: { - // Notify the server about file changes to '.clientrc files contained in the workspace - fileEvents: vscode.workspace.createFileSystemWatcher('**/*.heyvl') - } - }; - - // Create the language client and start the client. - this.client = new LanguageClient( - 'caesar', - 'Caesar', - serverOptions, - clientOptions - ); - context.subscriptions.push(this.client); - - // set up listeners for our custom events - context.subscriptions.push(this.client.onNotification("custom/verifyStatus", (params: VerifyStatusNotification) => { - for (let listener of this.updateListeners) { - listener(params.document, params.statuses); - } - })); - - context.subscriptions.push(this.client.onNotification("custom/computedPre", (params: ComputedPreNotification) => { - for (let listener of this.computedPreListeners) { - listener(params.document, params.pres); - } - })); - - // listen to onDidSaveTextDocument events - context.subscriptions.push(vscode.workspace.onDidSaveTextDocument((document) => { - // TODO: look at setting - this.verify(document); - })); - - // listen to commands - vscode.commands.registerCommand('caesar.restartServer', async () => { - await this.restart(); - }); - - vscode.commands.registerCommand('caesar.startServer', async () => { - await this.start(); - }); - - vscode.commands.registerCommand('caesar.stopServer', async () => { - await this.stop(); - }); - - vscode.commands.registerCommand('caesar.verify', async () => { - let openEditor = vscode.window.activeTextEditor; - if (openEditor) { - this.verify(openEditor.document); - } - }); - } - - async start() { - console.log("Starting Caesar"); - this.notifyStatusUpdate(ServerStatus.Starting); - await this.client.start(); - this.notifyStatusUpdate(ServerStatus.Ready); - } - - async restart() { - console.log("Restarting Caesar"); - this.client.restart(); - } - - async stop() { - console.log("Stopping Caesar"); - this.client.stop(); - } - - async verify(document: TextDocument) { - let documentItem = { - uri: document.uri.toString(), - languageId: document.languageId, - version: document.version, - text: document.getText() - }; - this.notifyStatusUpdate(ServerStatus.Verifying); - await this.client.sendRequest('custom/verify', { text_document: documentItem }); - // TODO: handle errors - this.notifyStatusUpdate(ServerStatus.Finished); - } - - public onStatusUpdate(callback: (status: ServerStatus) => void) { - this.statusListeners.push(callback); - } - - private notifyStatusUpdate(status: ServerStatus) { - for (let listener of this.statusListeners) { - listener(status); - } - } - - public onVerifyResult(callback: (document: TextDocumentIdentifier, results: Array<[Range, VerifyResult]>) => void) { - this.updateListeners.push(callback); - } - - public onComputedPre(callback: (document: TextDocumentIdentifier, results: Array<[Range, string]>) => void) { - this.computedPreListeners.push(callback); - } -} - export class Verifier { public context: ExtensionContext; @@ -204,237 +46,3 @@ export class Verifier { } } - -class StatusBarComponent { - - private enabled: boolean; - private status: ServerStatus = ServerStatus.Starting; - private view: StatusBarItem; - - constructor(verifier: Verifier) { - // create the view - this.view = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 99); - verifier.context.subscriptions.push(this.view); - this.view.text = "Caesar"; - - this.view.tooltip = new vscode.MarkdownString( - "[Restart Caesar](command:caesar.restartServer)\n\n" + - "[Start Caesar](command:caesar.startServer)\n\n" + - "[Stop Caesar](command:caesar.stopServer)" - , true); - - // render if enabled - this.enabled = StatusBarViewConfig.get("showStatusBar"); - this.render(); - - // subscribe to config changes - verifier.context.subscriptions.push(vscode.workspace.onDidChangeConfiguration((e: vscode.ConfigurationChangeEvent) => { - if (e.affectsConfiguration(CONFIGURATION_SECTION)) { - this.enabled = StatusBarViewConfig.get("showStatusBar"); - this.render(); - } - })); - - // listen to verifier updates - verifier.client.onStatusUpdate((status) => { - this.status = status; - this.render(); - }); - } - - render() { - if (this.enabled) { - switch (this.status) { - case ServerStatus.Starting: - this.view.text = "$(sync~spin) Starting Caesar..."; - break; - case ServerStatus.Ready: - this.view.text = "$(check) Caesar Ready"; - break; - case ServerStatus.Verifying: - this.view.text = "$(sync~spin) Verifying..."; - break; - case ServerStatus.Finished: - this.view.text = "$(check) Verified"; - break; - } - this.view.show(); - } else { - this.view.hide(); - } - } -} - -class GutterStatusComponent { - - private enabled: boolean; - private status: DocumentMap>; - - private verifyDecType: vscode.TextEditorDecorationType; - private failedDecType: vscode.TextEditorDecorationType; - private unknownDecType: vscode.TextEditorDecorationType; - - constructor(verifier: Verifier) { - // create decorations - this.verifyDecType = vscode.window.createTextEditorDecorationType({ gutterIconSize: "contain", gutterIconPath: verifier.context.asAbsolutePath('images/verified.png') }); - this.failedDecType = vscode.window.createTextEditorDecorationType({ gutterIconSize: "contain", gutterIconPath: verifier.context.asAbsolutePath('images/failed.png') }); - this.unknownDecType = vscode.window.createTextEditorDecorationType({ gutterIconSize: "contain", gutterIconPath: verifier.context.asAbsolutePath('images/unknown.png') }); - - // render if enabled - this.enabled = GutterInformationViewConfig.get("showGutterIcons"); - - this.status = new DocumentMap(); - - // subscribe to config changes - verifier.context.subscriptions.push(vscode.workspace.onDidChangeConfiguration((e: vscode.ConfigurationChangeEvent) => { - if (e.affectsConfiguration(CONFIGURATION_SECTION)) { - this.enabled = StatusBarViewConfig.get("showGutterIcons"); - this.render(); - } - })); - - // render when visible editors change - verifier.context.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors((_visibleEditors) => { - this.render(); - })); - - // listen to status and verify updates - verifier.client.onStatusUpdate((status) => { - if (status == ServerStatus.Verifying) { - for (let [_document, results] of this.status.entries()) { - results.length = 0; - } - this.render(); - } - }); - - verifier.client.onVerifyResult((document, results) => { - this.status.insert(document, results); - this.render(); - }); - } - - render() { - for (let [document_id, results] of this.status.entries()) { - for (let editor of vscode.window.visibleTextEditors) { - if (editor.document.uri.toString() !== document_id.uri) { - continue; - } - - let verifiedProcs: vscode.DecorationOptions[] = []; - let failedProcs: vscode.DecorationOptions[] = []; - let unknownProcs: vscode.DecorationOptions[] = []; - - if (this.enabled) { - for (let [range, result] of results) { - let line = range.start.line; - let gutterRange = new vscode.Range(line, 0, line, 0); - switch (result) { - case VerifyResult.Verified: - verifiedProcs.push({ range: gutterRange, hoverMessage: 'Verified' }); - break; - case VerifyResult.Failed: - failedProcs.push({ range: gutterRange, hoverMessage: 'Not Verified' }); - break; - case VerifyResult.Unknown: - unknownProcs.push({ range: gutterRange, hoverMessage: 'Unknown' }); - break; - } - } - } - - editor.setDecorations(this.verifyDecType, verifiedProcs); - editor.setDecorations(this.failedDecType, failedProcs); - editor.setDecorations(this.unknownDecType, unknownProcs); - } - } - } -} - -class ComputedPreComponent { - - private enabled: boolean; - private computedPres: DocumentMap>; - - private decorationType: TextEditorDecorationType; - - constructor(verifier: Verifier) { - // create decoration - this.decorationType = vscode.window.createTextEditorDecorationType({}); - - // set enabled flag - this.enabled = GutterInformationViewConfig.get("showGutterIcons"); - - this.computedPres = new DocumentMap(); - - // subscribe to config changes - verifier.context.subscriptions.push(vscode.workspace.onDidChangeConfiguration((e: vscode.ConfigurationChangeEvent) => { - if (e.affectsConfiguration(CONFIGURATION_SECTION)) { - this.enabled = InlineGhostTextViewConfig.get("showInlineGhostText"); - this.render(); - } - })); - - // render when visible text editors change - verifier.context.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors((_visibleEditors) => { - this.render(); - })); - - // listen to custom/computedPre notifications - verifier.client.onComputedPre((document, pres) => { - this.computedPres.insert(document, pres); - }); - - // clear all information when a new verification task is started - verifier.client.onStatusUpdate((status) => { - if (status == ServerStatus.Verifying) { - for (let [_document, results] of this.computedPres.entries()) { - results.length = 0; - } - this.render(); - } - }); - - // TODO: listen to content changes to remove lines? - } - - render() { - let backgroundColor = new vscode.ThemeColor('caesar.inlineGhostBackgroundColor'); - let color = new vscode.ThemeColor('caesar.inlineGhostForegroundColor'); - - for (let [document_id, pres] of this.computedPres.entries()) { - for (let editor of vscode.window.visibleTextEditors) { - if (editor.document.uri.toString() !== document_id.uri) { - continue; - } - - let decorations: vscode.DecorationOptions[] = []; - - if (this.enabled) { - for (let [range, text] of pres) { - let line = range.start.line; - if (line === 0) { - continue; - } - let lineAbove = line - 1; - let rangeAbove = new vscode.Range(lineAbove, 0, lineAbove, 0); - if (editor.document.lineAt(lineAbove).text.trim() === '') { - decorations.push({ - range: rangeAbove, - renderOptions: { - after: { - backgroundColor, - color, - contentText: text - } - } - }); - } - } - } - - editor.setDecorations(this.decorationType, decorations); - } - } - } -} From 18f162d2e9cdb8965ad7a49d8699a63a7b21e1b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Schro=CC=88er?= Date: Sat, 11 May 2024 23:32:17 +0200 Subject: [PATCH 18/25] k-induction: refactor code for more reuse --- src/proof_rules/induction.rs | 154 ++++++++++++++--------------------- 1 file changed, 63 insertions(+), 91 deletions(-) diff --git a/src/proof_rules/induction.rs b/src/proof_rules/induction.rs index 940d751..71ec463 100644 --- a/src/proof_rules/induction.rs +++ b/src/proof_rules/induction.rs @@ -28,8 +28,7 @@ use super::{Encoding, EncodingEnvironment, EncodingGenerated}; use super::util::*; -/// Syntactic sugar encoding for K-Induction encodings of type k=1 - +/// The "@induction" encoding is just syntactic sugar for 1-induction. pub struct InvariantAnnotation(pub AnnotationDecl); impl InvariantAnnotation { @@ -100,45 +99,9 @@ impl Encoding for InvariantAnnotation { inner_stmt: &Stmt, enc_env: EncodingEnvironment, ) -> Result { - // Unpack values from struct - let annotation_span = enc_env.annotation_span; - let direction = enc_env.direction; - - let mut visitor = ModifiedVariableCollector::new(); - visitor.visit_stmt(&mut inner_stmt.clone()).unwrap(); - let havoc_vars = visitor.modified_variables.into_iter().collect(); - let [invariant] = one_arg(args); - - let mut buf = vec![]; - - // Construct the specification of the k-induction encoding - buf.extend(encode_loop_spec( - annotation_span, - invariant, - invariant, - havoc_vars, - direction, - )); - - // Extend the loop k-1 times with the opposite direction - let next_iter = encode_extend( - annotation_span, - inner_stmt, - 0, - invariant, - direction.toggle(), - park_iteration_terminator(annotation_span, invariant, direction, tcx), - ); - - // Encode the last iteration in the normal direction - buf.push(encode_iter(annotation_span, inner_stmt, next_iter).unwrap()); - - Ok(EncodingGenerated { - span: annotation_span, - stmts: buf, - decls: None, - }) + let k = 1; + transform_k_induction(tcx, inner_stmt, enc_env, k, invariant) } fn is_terminator(&self) -> bool { @@ -210,6 +173,7 @@ impl Encoding for KIndAnnotation { | (CalculusType::Wlp, Direction::Down) ) } + fn transform( &self, tcx: &TyCtx, @@ -217,55 +181,9 @@ impl Encoding for KIndAnnotation { inner_stmt: &Stmt, enc_env: EncodingEnvironment, ) -> Result { - let annotation_span = enc_env.annotation_span; - let direction = enc_env.direction; - - let mut visitor = ModifiedVariableCollector::new(); - visitor.visit_stmt(&mut inner_stmt.clone()).unwrap(); - let havoc_vars = visitor.modified_variables.into_iter().collect(); - let [k, invariant] = two_args(args); - let k: u128 = lit_u128(k); - - let mut buf = vec![]; - - // Construct the specification of the k-induction encoding - buf.extend(encode_loop_spec( - annotation_span, - invariant, - invariant, - havoc_vars, - direction, - )); - - // If we do Park induction here, then use the terminator with error and - // success messages. If we do k-induction with k > 1, then do not emit - // these messages - they're not accurate then. - let terminator = if k == 1 { - park_iteration_terminator(annotation_span, invariant, direction, tcx) - } else { - iteration_terminator(annotation_span, invariant, direction, tcx) - }; - - // Extend the loop k-1 times with the opposite direction - let next_iter = encode_extend( - annotation_span, - inner_stmt, - k - 1, - invariant, - direction.toggle(), - terminator, - ); - - // Encode the last iteration in the normal direction - buf.push(encode_iter(annotation_span, inner_stmt, next_iter).unwrap()); - - Ok(EncodingGenerated { - span: annotation_span, - stmts: buf, - decls: None, - }) + transform_k_induction(tcx, inner_stmt, enc_env, k, invariant) } fn is_terminator(&self) -> bool { @@ -273,11 +191,65 @@ impl Encoding for KIndAnnotation { } } +/// Generic implementation of the encoding for both k-induction and induction. +/// Since induction is just 1-induction, we can reuse almost all of the code. +fn transform_k_induction( + tcx: &TyCtx, + inner_stmt: &Stmt, + enc_env: EncodingEnvironment, + k: u128, + invariant: &Expr, +) -> Result { + let annotation_span = enc_env.annotation_span; + let direction = enc_env.direction; + + let mut visitor = ModifiedVariableCollector::new(); + visitor.visit_stmt(&mut inner_stmt.clone()).unwrap(); + let havoc_vars = visitor.modified_variables.into_iter().collect(); + + let mut buf = vec![]; + + // Construct the specification of the k-induction encoding + buf.extend(encode_loop_spec( + annotation_span, + invariant, + havoc_vars, + direction, + )); + + // If we do Park induction here, then use the terminator with error and + // success messages. If we do k-induction with k > 1, then do not emit + // these messages - they're not accurate then. + let terminator = if k == 1 { + park_iteration_terminator(annotation_span, invariant, direction, tcx) + } else { + iteration_terminator(annotation_span, invariant, direction, tcx) + }; + + // Extend the loop k-1 times with the opposite direction + let next_iter = encode_extend( + annotation_span, + inner_stmt, + k - 1, + invariant, + direction.toggle(), + terminator, + ); + + // Encode the last iteration in the normal direction + buf.push(encode_iter(annotation_span, inner_stmt, next_iter).unwrap()); + + Ok(EncodingGenerated { + span: annotation_span, + stmts: buf, + decls: None, + }) +} + /// Encode the loop "spec call" with respective error messages. fn encode_loop_spec( span: Span, - pre: &Expr, - post: &Expr, + invariant: &Expr, variables: Vec, direction: Direction, ) -> Vec { @@ -288,13 +260,13 @@ fn encode_loop_spec( let error_msg = format!("pre might not entail the invariant ({})", error_condition); vec![ wrap_with_error_message( - Spanned::new(span, StmtKind::Assert(direction, pre.clone())), + Spanned::new(span, StmtKind::Assert(direction, invariant.clone())), &error_msg, ), Spanned::new(span, StmtKind::Havoc(direction, variables)), Spanned::new(span, StmtKind::Validate(direction)), wrap_with_success_message( - Spanned::new(span, StmtKind::Assume(direction, post.clone())), + Spanned::new(span, StmtKind::Assume(direction, invariant.clone())), "invariant not necessary for inductivity", ), ] From 34f6147b039e6af924b4269b11b7af22f820754e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Schro=CC=88er?= Date: Tue, 14 May 2024 15:52:05 +0200 Subject: [PATCH 19/25] vscode-ext: add HeyVL snippets and move files --- .../{syntaxes => heyvl}/heyvl.tmLanguage.json | 0 .../{ => heyvl}/language-configuration.json | 0 vscode-ext/heyvl/snippets.json | 201 ++++++++++++++++++ vscode-ext/package.json | 10 +- 4 files changed, 209 insertions(+), 2 deletions(-) rename vscode-ext/{syntaxes => heyvl}/heyvl.tmLanguage.json (100%) rename vscode-ext/{ => heyvl}/language-configuration.json (100%) create mode 100644 vscode-ext/heyvl/snippets.json diff --git a/vscode-ext/syntaxes/heyvl.tmLanguage.json b/vscode-ext/heyvl/heyvl.tmLanguage.json similarity index 100% rename from vscode-ext/syntaxes/heyvl.tmLanguage.json rename to vscode-ext/heyvl/heyvl.tmLanguage.json diff --git a/vscode-ext/language-configuration.json b/vscode-ext/heyvl/language-configuration.json similarity index 100% rename from vscode-ext/language-configuration.json rename to vscode-ext/heyvl/language-configuration.json diff --git a/vscode-ext/heyvl/snippets.json b/vscode-ext/heyvl/snippets.json new file mode 100644 index 0000000..380891a --- /dev/null +++ b/vscode-ext/heyvl/snippets.json @@ -0,0 +1,201 @@ +{ + "Proc Declaration": { + "prefix": [ + "proc" + ], + "body": [ + "proc ${1:name}(${2:}) -> (${3:}) {", + "\t$0", + "}" + ], + "description": "A proc declaration." + }, + "Coproc Declaration": { + "prefix": [ + "coproc" + ], + "body": [ + "coproc ${1:name}(${2:}) -> (${3:}) {", + "\t$0", + "}" + ], + "description": "A coproc declaration." + }, + "Domain Declaration": { + "prefix": [ + "domain" + ], + "body": [ + "domain ${1:Name} {", + "\t$0", + "}" + ], + "description": "A domain declaration." + }, + "Func Declaration": { + "prefix": [ + "func" + ], + "body": [ + "func ${1:name}($2): $0" + ], + "description": "An uninterpreted function declaration (func)." + }, + "Func Definition": { + "prefix": [ + "funcdef" + ], + "body": [ + "func ${1:name}($2): ${1:UInt} = $0" + ], + "description": "An uninterpreted function definition with a body." + }, + "Axiom Declaration": { + "prefix": [ + "axiom" + ], + "body": [ + "axiom ${1:axiom$RANDOM_HEX} $0" + ], + "description": "An axiom declaration." + }, + "Axiom-Forall Declaration": { + "prefix": [ + "axforall" + ], + "body": [ + "axiom ${1:axiom$RANDOM_HEX} forall ${2:}. $0" + ], + "description": "An axiom declaration with a forall quantifier inside." + }, + "Variable Declaration Statement": { + "prefix": [ + "var" + ], + "body": [ + "var ${1:name}: $2 " + ], + "description": "A variable declaration statement." + }, + "Variable Initialization Statement": { + "prefix": [ + "vardecl" + ], + "body": [ + "var ${1:name}: $2 = $0" + ], + "description": "A variable declaration statement with an initializer." + }, + "Coin Flip Statement": { + "prefix": [ + "flip" + ], + "body": [ + "var ${1:prob_choice}: Bool = flip(${2:0.5})" + ], + "description": "A coin flip." + }, + "If Statement": { + "prefix": [ + "if" + ], + "body": [ + "if $1 {", + "\t$0", + "} else {", + "\t", + "}" + ], + "description": "An if-then-else statement." + }, + "Boolean Assume Statement": { + "prefix": [ + "bassume" + ], + "body": [ + "assume ?($0)" + ], + "description": "A Boolean assumption statement." + }, + "Boolean Assert Statement": { + "prefix": [ + "bassert" + ], + "body": [ + "assert ?($0)" + ], + "description": "A Boolean assertion statement." + }, + "Boolean Coassume Statement": { + "prefix": [ + "bcoassume" + ], + "body": [ + "coassume !?($0)" + ], + "description": "A Boolean coassumption statement." + }, + "Boolean Coassert Statement": { + "prefix": [ + "bcoassert" + ], + "body": [ + "coassert !?($0)" + ], + "description": "A Boolean coassertion statement." + }, + "Constant Assertion Statement": { + "prefix": [ + "assertconst" + ], + "body": [ + "assert $1; assume ?(false)" + ], + "description": "A constant assertion statement." + }, + "Constant Coassertion Statement": { + "prefix": [ + "coassertconst" + ], + "body": [ + "coassert $1; coassume !?(false)" + ], + "description": "A constant coassertion statement." + }, + "Reward Statement": { + "prefix": [ + "reward" + ], + "body": [ + "reward ${1:1}" + ], + "description": "A reward statement." + }, + "Forall Expression": { + "prefix": [ + "forall" + ], + "body": [ + "forall $1. $0" + ], + "description": "A forall expression." + }, + "Exists Expression": { + "prefix": [ + "exists" + ], + "body": [ + "exists $1. $0" + ], + "description": "An exists expression." + }, + "Ite Expression": { + "prefix": [ + "ite" + ], + "body": [ + "ite($1, $2, $0)" + ], + "description": "An ite expression (if-then-else)." + } +} \ No newline at end of file diff --git a/vscode-ext/package.json b/vscode-ext/package.json index 8f31983..fbd1897 100644 --- a/vscode-ext/package.json +++ b/vscode-ext/package.json @@ -39,14 +39,20 @@ "extensions": [ ".heyvl" ], - "configuration": "./language-configuration.json" + "configuration": "./heyvl/language-configuration.json" } ], "grammars": [ { "language": "heyvl", "scopeName": "source.heyvl", - "path": "./syntaxes/heyvl.tmLanguage.json" + "path": "./heyvl/heyvl.tmLanguage.json" + } + ], + "snippets": [ + { + "language": "heyvl", + "path": "./heyvl/snippets.json" } ], "configuration": { From 5bc09ac2838c7f073d1becb76e47333400aefaf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Schro=CC=88er?= Date: Tue, 14 May 2024 17:48:45 +0200 Subject: [PATCH 20/25] tracing: emit tracing info to stderr --- src/timing.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/timing.rs b/src/timing.rs index 70d093c..27333d3 100644 --- a/src/timing.rs +++ b/src/timing.rs @@ -77,7 +77,8 @@ impl DispatchBuilder { cfg_if::cfg_if! { if #[cfg(not(test))] { logging_layer = tracing_subscriber::fmt::layer() - .with_span_events(tracing_subscriber::fmt::format::FmtSpan::CLOSE); + .with_span_events(tracing_subscriber::fmt::format::FmtSpan::CLOSE) + .with_writer(std::io::stderr); } else { use tracing_subscriber::fmt::format::*; logging_layer = tracing_subscriber::fmt::layer() From 6e48738acd998c4d4cc71ff9fd6ac121b0c607e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Schro=CC=88er?= Date: Tue, 14 May 2024 18:14:21 +0200 Subject: [PATCH 21/25] vscode-extension: a first README --- vscode-ext/README.md | 76 +++++++++++--------------------- vscode-ext/images/icon.afdesign | Bin 0 -> 44967 bytes vscode-ext/images/icon.png | Bin 0 -> 37505 bytes vscode-ext/package.json | 11 +++-- 4 files changed, 33 insertions(+), 54 deletions(-) create mode 100644 vscode-ext/images/icon.afdesign create mode 100644 vscode-ext/images/icon.png diff --git a/vscode-ext/README.md b/vscode-ext/README.md index 61adf17..31a5be2 100644 --- a/vscode-ext/README.md +++ b/vscode-ext/README.md @@ -1,71 +1,45 @@ -# caesar README +# The Deductive Verifier *Caesar* for VSCode -This is the README for your extension "caesar". After writing up a brief description, we recommend including the following sections. +This is the VSCode extension for the [Caesar deductive verifier](https://www.caesarverifier.org). +Caesar is a verifier for probabilistic and quantitative programs and thus supports reasoning about quantitative specifications such as "the expected runtime is at most `2x`". +Caesar uses the *HeyVL* language as its quantitative *intermediate verification language* (IVL). +This VSCode extension recognizes the `.heyvl` file extension. -## Features - -Describe specific features of your extension including screenshots of your extension in action. Image paths are relative to this README file. +You can find more information about Caesar and HeyVL on the website: https://www.caesarverifier.org/. -For example if there is an image subfolder under your extension project workspace: +On the website, you can also download the Caesar command-line binary for more advanced use cases that are not included in this VSCode extension. \!\[feature X\]\(images/feature-x.png\) -> Tip: Many popular extensions utilize animations. This is an excellent way to show off your extension! We recommend short, focused animations that are easy to follow. - -## Requirements +## Features -If you have any requirements or dependencies, add a section describing those and how to install and configure them. + * Syntax highlighting and language configuration for HeyVL. + * Snippets for HeyVL. + * Verify HeyVL files on file save or on command. + * Verification errors and successes are shown in the gutter via icons. + * Diagnostics such as errors or warnings are shown in the code and in the "Problems" menu in VSCode. -## Extension Settings +## Requirements -Include if your extension adds any VS Code settings through the `contributes.configuration` extension point. +You will need to provide the Caesar binary for the extension to run. +See [installation instructions](https://www.caesarverifier.org/docs/getting-started/installation) for more information. -For example: +We provide binaries for MacOS (ARM and x86-64), Windows (x86-64), and Debian/Linux (x86-64). -This extension contributes the following settings: +## Extension Settings -* `myExtension.enable`: Enable/disable this extension. -* `myExtension.thing`: Set to `blah` to do something. +You can find Caesar's settings in the settings menu in the "Caesar" section. +Importantly, you will need to configure how the Caesar binary is started. ## Known Issues -Calling out known issues can help limit users opening duplicate issues against your extension. +This is a very new VSCode extension for Caesar. +If you encounter any issues, [feel free to open an issue](https://github.com/moves-rwth/caesar/issues). ## Release Notes -Users appreciate release notes as you update your extension. - -### 1.0.0 - -Initial release of ... - -### 1.0.1 - -Fixed issue #. - -### 1.1.0 - -Added features X, Y, and Z. - ---- - -## Following extension guidelines - -Ensure that you've read through the extensions guidelines and follow the best practices for creating your extension. - -* [Extension Guidelines](https://code.visualstudio.com/api/references/extension-guidelines) - -## Working with Markdown - -You can author your README using Visual Studio Code. Here are some useful editor keyboard shortcuts: - -* Split the editor (`Cmd+\` on macOS or `Ctrl+\` on Windows and Linux). -* Toggle preview (`Shift+Cmd+V` on macOS or `Shift+Ctrl+V` on Windows and Linux). -* Press `Ctrl+Space` (Windows, Linux, macOS) to see a list of Markdown snippets. - -## For more information +On Github, we have a list of all of [Caesar's releases](https://github.com/moves-rwth/caesar/releases) along with binaries. -* [Visual Studio Code's Markdown Support](http://code.visualstudio.com/docs/languages/markdown) -* [Markdown Syntax Reference](https://help.github.com/articles/markdown-basics/) +### 0.0.1 -**Enjoy!** +Initial release. diff --git a/vscode-ext/images/icon.afdesign b/vscode-ext/images/icon.afdesign new file mode 100644 index 0000000000000000000000000000000000000000..d1f962b012d808392dacc9bb533d2eb10a4644e7 GIT binary patch literal 44967 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 literal 0 HcmV?d00001 diff --git a/vscode-ext/package.json b/vscode-ext/package.json index fbd1897..64c7ca0 100644 --- a/vscode-ext/package.json +++ b/vscode-ext/package.json @@ -1,13 +1,18 @@ { "name": "caesar", - "displayName": "caesar", - "description": "VSCode Extension of the Deductive Probabilistic Program Verifier Caesar", + "displayName": "Caesar Verifier", + "description": "The quantitative deductive verifier Caesar for VSCode", "version": "0.0.1", "engines": { "vscode": "^1.87.0" }, "categories": [ - "Other" + "Programming Languages" + ], + "icon": "images/icon.png", + "tags": [ + "verification", + "snippet" ], "main": "./out/extension.js", "contributes": { From f31bba4652d5609f167d3fa244c079154f23089a Mon Sep 17 00:00:00 2001 From: umutdural Date: Tue, 14 May 2024 18:27:07 +0200 Subject: [PATCH 22/25] vscode-ext: fixed gutter icon option bug --- vscode-ext/src/GutterStatusComponent.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vscode-ext/src/GutterStatusComponent.ts b/vscode-ext/src/GutterStatusComponent.ts index 7591c7e..2498aac 100644 --- a/vscode-ext/src/GutterStatusComponent.ts +++ b/vscode-ext/src/GutterStatusComponent.ts @@ -27,7 +27,7 @@ export class GutterStatusComponent { // subscribe to config changes verifier.context.subscriptions.push(vscode.workspace.onDidChangeConfiguration((e: vscode.ConfigurationChangeEvent) => { if (e.affectsConfiguration(CONFIGURATION_SECTION)) { - this.enabled = StatusBarViewConfig.get("showGutterIcons"); + this.enabled = GutterInformationViewConfig.get("showGutterIcons"); this.render(); } })); From 33603eb07a5722b3113cdaa3dabe8376d12a4a32 Mon Sep 17 00:00:00 2001 From: umutdural Date: Tue, 14 May 2024 18:27:24 +0200 Subject: [PATCH 23/25] vscode-ext: caesar source/binary options, basic start failure handling --- vscode-ext/package.json | 23 +++++ vscode-ext/src/CaesarClient.ts | 140 ++++++++++++++++++++------- vscode-ext/src/Configuration.ts | 10 +- vscode-ext/src/StatusBarComponent.ts | 8 +- vscode-ext/src/constants.ts | 17 ++++ vscode-ext/src/extension.ts | 6 +- 6 files changed, 164 insertions(+), 40 deletions(-) create mode 100644 vscode-ext/src/constants.ts diff --git a/vscode-ext/package.json b/vscode-ext/package.json index 64c7ca0..e6c4418 100644 --- a/vscode-ext/package.json +++ b/vscode-ext/package.json @@ -64,6 +64,29 @@ "type": "object", "title": "Caesar", "properties": { + "caesar.server.installationOptions": { + "type": "string", + "default": "binary", + "enum": [ + "binary", + "source-code" + ], + "enumDescriptions": [ + "Use the binary of Caesar", + "Build Caesar from the source code" + ], + "description": "Specifies how caesar will be executed from the extension." + }, + "caesar.server.autoStartServer": { + "type": "boolean", + "default": false, + "description": "Specifies whether to automatically start the server when the extension is activated." + }, + "caesar.server.path": { + "type": "string", + "default": "", + "description": "Specifies the path to the Caesar binary or source code." + }, "caesar.uI.gutterIcons.showGutterIcons": { "type": "boolean", "default": true, diff --git a/vscode-ext/src/CaesarClient.ts b/vscode-ext/src/CaesarClient.ts index 946111a..49f5472 100644 --- a/vscode-ext/src/CaesarClient.ts +++ b/vscode-ext/src/CaesarClient.ts @@ -2,8 +2,13 @@ import { LanguageClientOptions, TextDocumentIdentifier, VersionedTextDocumentIde import { LanguageClient, ServerOptions } from "vscode-languageclient/node"; import { ExtensionContext, Range, TextDocument } from "vscode"; import * as vscode from "vscode"; +import { ConfigurationConstants } from "./constants"; +import { ServerConfig } from "./Configuration"; +import path from "path"; +import fs from 'fs'; export enum ServerStatus { + Stopped, Starting, Ready, FailedToStart, @@ -29,37 +34,98 @@ export type ComputedPreNotification = { export class CaesarClient { - private client: LanguageClient; + private client: LanguageClient | null; + private context: ExtensionContext; private statusListeners: Array<(status: ServerStatus) => void> = new Array(); private updateListeners: Array<(document: TextDocumentIdentifier, results: Array<[Range, VerifyResult]>) => void> = new Array(); private computedPreListeners: Array<(document: TextDocumentIdentifier, results: Array<[Range, string]>) => void> = new Array(); + constructor(context: ExtensionContext) { + this.context = context; + // Initialize and start the server if the autoStartServer configuration is set otherwise set the client to null + this.client = this.initialize(context); + + // listen to commands + vscode.commands.registerCommand('caesar.restartServer', async () => { + await this.restart(); + }); + + vscode.commands.registerCommand('caesar.startServer', async () => { + await this.start(); + }); + + vscode.commands.registerCommand('caesar.stopServer', async () => { + await this.stop(); + }); + } + + /// Try to initialize the client and return the client if successful otherwise return null + private initialize(context: ExtensionContext): LanguageClient | null { + try { + this.client = this.create_client(context); + } catch (error) { + this.notifyStatusUpdate(ServerStatus.FailedToStart); + vscode.window.showErrorMessage("Failed to initialize Caesar") + console.error(error) + this.client = null; + } + + return this.client; + } + + private create_client(context: vscode.ExtensionContext): LanguageClient { + // Get the source code / binary path from the configurations + let serverPath: string = ServerConfig.get(ConfigurationConstants.installationPath); + if (serverPath === "") { + vscode.window.showErrorMessage("Caesar: Installation path is not set. Please set the path in the settings.") + throw new Error("Installation path is not set") + } + let serverExecutable = ""; + let args: string[] = []; + switch (ServerConfig.get(ConfigurationConstants.installationOptions)) { + case ConfigurationConstants.binaryOption: + serverExecutable = "caesar"; + args = ['--language-server']; + break; + case ConfigurationConstants.sourceCodeOption: + if (!fs.existsSync(path.resolve(serverPath, "Cargo.toml"))) { + vscode.window.showErrorMessage("Caesar: Cargo.toml file is not found in the path. Please check the path in the settings.") + throw new Error("Cargo.toml file is not found in the path") + } + serverExecutable = "cargo"; + args = ['run', '--', '--language-server']; + break; + } + + // If the extension is launched in debug mode then the debug server options are used + // Otherwise the run options are used let serverOptions: ServerOptions = { run: { - command: 'cargo', - args: ['run', '--', '--language-server'], + command: serverExecutable, + args: args, options: { - - }, // TODO!! + cwd: serverPath, + } }, debug: { - command: 'cargo', - args: ['run', '--', '--language-server'], + command: serverExecutable, + args: args, options: { - + cwd: serverPath, env: { ...process.env, - "RUST_LOG": "caesar=info", "NO_COLOR": "1", "RUST_BACKTRACE": "1" } - }, // TODO!! + } } }; + // Options to control the language client let clientOptions: LanguageClientOptions = { diagnosticCollectionName: 'caesar', + // Register the server for heyvl documents documentSelector: [{ scheme: 'file', language: 'heyvl' }], synchronize: { // Notify the server about file changes to '.clientrc files contained in the workspace @@ -67,23 +133,23 @@ export class CaesarClient { } }; - // Create the language client and start the client. - this.client = new LanguageClient( + let client = new LanguageClient( 'caesar', 'Caesar', serverOptions, clientOptions ); - context.subscriptions.push(this.client); + + context.subscriptions.push(client) // set up listeners for our custom events - context.subscriptions.push(this.client.onNotification("custom/verifyStatus", (params: VerifyStatusNotification) => { + context.subscriptions.push(client.onNotification("custom/verifyStatus", (params: VerifyStatusNotification) => { for (let listener of this.updateListeners) { listener(params.document, params.statuses); } })); - context.subscriptions.push(this.client.onNotification("custom/computedPre", (params: ComputedPreNotification) => { + context.subscriptions.push(client.onNotification("custom/computedPre", (params: ComputedPreNotification) => { for (let listener of this.computedPreListeners) { listener(params.document, params.pres); } @@ -92,48 +158,56 @@ export class CaesarClient { // listen to onDidSaveTextDocument events context.subscriptions.push(vscode.workspace.onDidSaveTextDocument((document) => { // TODO: look at setting + if (document.languageId !== "heyvl") { + return + } this.verify(document); })); - // listen to commands - vscode.commands.registerCommand('caesar.restartServer', async () => { - await this.restart(); - }); - - vscode.commands.registerCommand('caesar.startServer', async () => { - await this.start(); - }); - - vscode.commands.registerCommand('caesar.stopServer', async () => { - await this.stop(); - }); - vscode.commands.registerCommand('caesar.verify', async () => { let openEditor = vscode.window.activeTextEditor; if (openEditor) { this.verify(openEditor.document); } }); + return client; } async start() { console.log("Starting Caesar"); this.notifyStatusUpdate(ServerStatus.Starting); - await this.client.start(); + // If the client is null, try initializing it and if it also fails show an error message + if (this.client === null) { + // First initialize the client by creating a new one, if it fails return + if (this.initialize(this.context) === null) { + return + }; + } + await this.client!.start(); this.notifyStatusUpdate(ServerStatus.Ready); + } async restart() { - console.log("Restarting Caesar"); - this.client.restart(); + if (this.client === null) { + this.start() + return + } else { + console.log("Restarting Caesar"); + this.client?.restart(); + } } async stop() { console.log("Stopping Caesar"); - this.client.stop(); + this.client?.stop(); + this.notifyStatusUpdate(ServerStatus.Stopped); } async verify(document: TextDocument) { + if (this.client === null) { + return + } let documentItem = { uri: document.uri.toString(), languageId: document.languageId, @@ -163,4 +237,4 @@ export class CaesarClient { public onComputedPre(callback: (document: TextDocumentIdentifier, results: Array<[Range, string]>) => void) { this.computedPreListeners.push(callback); } -} \ No newline at end of file +} diff --git a/vscode-ext/src/Configuration.ts b/vscode-ext/src/Configuration.ts index f44ef18..808d42f 100644 --- a/vscode-ext/src/Configuration.ts +++ b/vscode-ext/src/Configuration.ts @@ -41,11 +41,11 @@ export class ConfigCategory { // Root Configurations: -export const ViewConfiguration = new ConfigCategory("uI", null); - +export const ViewConfig = new ConfigCategory("uI", null); +export const ServerConfig = new ConfigCategory("server", null); // View Configurations: -export const GutterInformationViewConfig = new ConfigCategory('gutterIcons', ViewConfiguration,); -export const StatusBarViewConfig = new ConfigCategory('statusBar', ViewConfiguration); -export const InlineGhostTextViewConfig = new ConfigCategory('inlineGhostText', ViewConfiguration); +export const GutterInformationViewConfig = new ConfigCategory('gutterIcons', ViewConfig); +export const StatusBarViewConfig = new ConfigCategory('statusBar', ViewConfig); +export const InlineGhostTextViewConfig = new ConfigCategory('inlineGhostText', ViewConfig); diff --git a/vscode-ext/src/StatusBarComponent.ts b/vscode-ext/src/StatusBarComponent.ts index 1376b9f..a571820 100644 --- a/vscode-ext/src/StatusBarComponent.ts +++ b/vscode-ext/src/StatusBarComponent.ts @@ -7,7 +7,7 @@ import { Verifier } from "./Verifier"; export class StatusBarComponent { private enabled: boolean; - private status: ServerStatus = ServerStatus.Starting; + private status: ServerStatus = ServerStatus.Stopped; private view: StatusBarItem; constructor(verifier: Verifier) { @@ -44,6 +44,12 @@ export class StatusBarComponent { render() { if (this.enabled) { switch (this.status) { + case ServerStatus.Stopped: + this.view.text = "$(debug-stop) Et tu, Brute?"; + break; + case ServerStatus.FailedToStart: + this.view.text = "$(warning) Failed to start Caesar"; + break; case ServerStatus.Starting: this.view.text = "$(sync~spin) Starting Caesar..."; break; diff --git a/vscode-ext/src/constants.ts b/vscode-ext/src/constants.ts new file mode 100644 index 0000000..4361ea3 --- /dev/null +++ b/vscode-ext/src/constants.ts @@ -0,0 +1,17 @@ + +export const enum LanguageClientConstants { + id = "caesar", + name = "Caesar", +} + + +export const enum ConfigurationConstants { + installationOptions = "installationOptions", + showGutterIcons = "showGutterIcons", + showStatusBar = "showStatusBar", + showInlineGhostText = "showInlineGhostText", + installationPath = "path", + autoStartServer = "autoStartServer", + binaryOption = "binary", + sourceCodeOption = "source-code", +} diff --git a/vscode-ext/src/extension.ts b/vscode-ext/src/extension.ts index f3786c1..76de5ca 100644 --- a/vscode-ext/src/extension.ts +++ b/vscode-ext/src/extension.ts @@ -2,12 +2,16 @@ // Import the module and reference it with the alias vscode in your code below import * as vscode from 'vscode'; import { Verifier } from './Verifier'; +import { ServerConfig } from './Configuration'; +import { ConfigurationConstants } from './constants'; // This method is called when your extension is activated // Your extension is activated the very first time the command is executed export function activate(context: vscode.ExtensionContext) { let verifier = new Verifier(context); - verifier.start(); + if (ServerConfig.get(ConfigurationConstants.autoStartServer)) { + verifier.start(); + } } // This method is called when the extension is deactivated From a269ab534f482e6d981d85f66bd15383461f5786 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Schro=CC=88er?= Date: Tue, 14 May 2024 18:53:22 +0200 Subject: [PATCH 24/25] vscode-ext: make eslint do typechecking --- .vscode/settings.json | 20 ++-- vscode-ext/.eslintignore | 3 + vscode-ext/.eslintrc.json | 30 ----- vscode-ext/eslint.config.mjs | 42 +++++++ vscode-ext/package-lock.json | 194 ++++++++++++++++++--------------- vscode-ext/package.json | 12 +- vscode-ext/src/CaesarClient.ts | 8 +- vscode-ext/tsconfig.json | 2 +- 8 files changed, 176 insertions(+), 135 deletions(-) create mode 100644 vscode-ext/.eslintignore delete mode 100644 vscode-ext/.eslintrc.json create mode 100644 vscode-ext/eslint.config.mjs diff --git a/.vscode/settings.json b/.vscode/settings.json index e6b786d..5c5a2bf 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,10 +1,14 @@ { - "files.exclude": { - "vscode-ext/out": false // set this to true to hide the "out" folder with the compiled JS files - }, - "search.exclude": { - "vscode-ext/out": true // set this to false to include "out" folder in search results - }, - // Turn off tsc task auto detection since we have the necessary tasks as npm scripts - "typescript.tsc.autoDetect": "off" + "files.exclude": { + "vscode-ext/out": false // set this to true to hide the "out" folder with the compiled JS files + }, + "search.exclude": { + "vscode-ext/out": true // set this to false to include "out" folder in search results + }, + // Turn off tsc task auto detection since we have the necessary tasks as npm scripts + "typescript.tsc.autoDetect": "off", + "eslint.workingDirectories": [ + "vscode-ext" + ], + "eslint.experimental.useFlatConfig": true } \ No newline at end of file diff --git a/vscode-ext/.eslintignore b/vscode-ext/.eslintignore new file mode 100644 index 0000000..224ecd9 --- /dev/null +++ b/vscode-ext/.eslintignore @@ -0,0 +1,3 @@ +out/**/* +dist/**/* +**/*.d.ts \ No newline at end of file diff --git a/vscode-ext/.eslintrc.json b/vscode-ext/.eslintrc.json deleted file mode 100644 index 86c86f3..0000000 --- a/vscode-ext/.eslintrc.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "root": true, - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": 6, - "sourceType": "module" - }, - "plugins": [ - "@typescript-eslint" - ], - "rules": { - "@typescript-eslint/naming-convention": [ - "warn", - { - "selector": "import", - "format": [ "camelCase", "PascalCase" ] - } - ], - "@typescript-eslint/semi": "warn", - "curly": "warn", - "eqeqeq": "warn", - "no-throw-literal": "warn", - "semi": "off" - }, - "ignorePatterns": [ - "out", - "dist", - "**/*.d.ts" - ] -} \ No newline at end of file diff --git a/vscode-ext/eslint.config.mjs b/vscode-ext/eslint.config.mjs new file mode 100644 index 0000000..79270b3 --- /dev/null +++ b/vscode-ext/eslint.config.mjs @@ -0,0 +1,42 @@ +import eslint from '@eslint/js'; +import tseslint from 'typescript-eslint'; + +export default tseslint.config( + eslint.configs.recommended, + ...tseslint.configs.recommendedTypeChecked, + ...tseslint.configs.stylistic, + { + "languageOptions": { + "parserOptions": { + "project": "tsconfig.json", + tsconfigRootDir: import.meta.dirname, + "ecmaVersion": 6, + "sourceType": "module" + } + }, + "rules": { + "@typescript-eslint/naming-convention": [ + "warn", + { + "selector": "import", + "format": [ + "camelCase", + "PascalCase" + ] + }, + ], + "@typescript-eslint/no-unused-vars": [ + "error", + { + "destructuredArrayIgnorePattern": "^_" + } + ], + "@typescript-eslint/semi": "warn", + "curly": "warn", + "eqeqeq": "warn", + "no-throw-literal": "warn", + "semi": "off", + "@typescript-eslint/no-floating-promises": "error", + "@typescript-eslint/no-explicit-any": "off" + }, + }); \ No newline at end of file diff --git a/vscode-ext/package-lock.json b/vscode-ext/package-lock.json index 19925dd..51c270c 100644 --- a/vscode-ext/package-lock.json +++ b/vscode-ext/package-lock.json @@ -8,9 +8,10 @@ "name": "caesar", "version": "0.0.1", "dependencies": { - "vscode-languageclient": "9.0.1" + "vscode-languageclient": "^9.0.1" }, "devDependencies": { + "@eslint/js": "^9.2.0", "@types/mocha": "^10.0.6", "@types/node": "18.x", "@types/vscode": "^1.87.0", @@ -19,7 +20,8 @@ "@vscode/test-cli": "^0.0.6", "@vscode/test-electron": "^2.3.9", "eslint": "^8.56.0", - "typescript": "^5.3.3" + "typescript": "^5.3.3", + "typescript-eslint": "^7.9.0" }, "engines": { "vscode": "^1.87.0" @@ -110,12 +112,12 @@ } }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.2.0.tgz", + "integrity": "sha512-ESiIudvhoYni+MdsI8oD7skpprZ89qKocwRM2KEvhhBJ9nl5MRh7BXU5GTod7Mdygq+AUl+QzId6iWJKR/wABA==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@humanwhocodes/config-array": { @@ -311,12 +313,6 @@ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", "dev": true }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, "node_modules/@types/mocha": { "version": "10.0.6", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", @@ -332,12 +328,6 @@ "undici-types": "~5.26.4" } }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true - }, "node_modules/@types/vscode": { "version": "1.87.0", "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.87.0.tgz", @@ -345,25 +335,23 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.1.tgz", - "integrity": "sha512-zioDz623d0RHNhvx0eesUmGfIjzrk18nSBC8xewepKXbBvN/7c1qImV7Hg8TI1URTxKax7/zxfxj3Uph8Chcuw==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.9.0.tgz", + "integrity": "sha512-6e+X0X3sFe/G/54aC3jt0txuMTURqLyekmEHViqyA2VnxhLMpvA6nqmcjIy+Cr9tLDHPssA74BP5Mx9HQIxBEA==", "dev": true, "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/type-utils": "7.1.1", - "@typescript-eslint/utils": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", - "debug": "^4.3.4", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.9.0", + "@typescript-eslint/type-utils": "7.9.0", + "@typescript-eslint/utils": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0", "graphemer": "^1.4.0", - "ignore": "^5.2.4", + "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -380,19 +368,19 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.1.tgz", - "integrity": "sha512-ZWUFyL0z04R1nAEgr9e79YtV5LbafdOtN7yapNbn1ansMyaegl2D4bL7vHoJ4HPSc4CaLwuCVas8CVuneKzplQ==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.9.0.tgz", + "integrity": "sha512-qHMJfkL5qvgQB2aLvhUSXxbK7OLnDkwPzFalg458pxQgfxKDfT1ZDbHQM/I6mDIf/svlMkj21kzKuQ2ixJlatQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/typescript-estree": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/scope-manager": "7.9.0", + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/typescript-estree": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0", "debug": "^4.3.4" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -408,16 +396,16 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", - "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.9.0.tgz", + "integrity": "sha512-ZwPK4DeCDxr3GJltRz5iZejPFAAr4Wk3+2WIBaj1L5PYK5RgxExu/Y68FFVclN0y6GGwH8q+KgKRCvaTmFBbgQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1" + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -425,18 +413,18 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.1.tgz", - "integrity": "sha512-5r4RKze6XHEEhlZnJtR3GYeCh1IueUHdbrukV2KSlLXaTjuSfeVF8mZUVPLovidCuZfbVjfhi4c0DNSa/Rdg5g==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.9.0.tgz", + "integrity": "sha512-6Qy8dfut0PFrFRAZsGzuLoM4hre4gjzWJB6sUvdunCYZsYemTkzZNwF1rnGea326PHPT3zn5Lmg32M/xfJfByA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.1.1", - "@typescript-eslint/utils": "7.1.1", + "@typescript-eslint/typescript-estree": "7.9.0", + "@typescript-eslint/utils": "7.9.0", "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -452,12 +440,12 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", - "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.9.0.tgz", + "integrity": "sha512-oZQD9HEWQanl9UfsbGVcZ2cGaR0YT5476xfWE0oE5kQa2sNK2frxOlkeacLOTh9po4AlUT5rtkGyYM5kew0z5w==", "dev": true, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -465,22 +453,22 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", - "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.9.0.tgz", + "integrity": "sha512-zBCMCkrb2YjpKV3LA0ZJubtKCDxLttxfdGmwZvTqqWevUPN0FZvSI26FalGFFUZU/9YQK/A4xcQF9o/VVaCKAg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/visitor-keys": "7.9.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -493,21 +481,18 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.1.tgz", - "integrity": "sha512-thOXM89xA03xAE0lW7alstvnyoBUbBX38YtY+zAUcpRPcq9EIhXPuJ0YTv948MbzmKh6e1AUszn5cBFK49Umqg==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.9.0.tgz", + "integrity": "sha512-5KVRQCzZajmT4Ep+NEgjXCvjuypVvYHUW7RHlXzNPuak2oWpVoD1jf5xCP0dPAuNIchjC7uQyvbdaSTFaLqSdA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/typescript-estree": "7.1.1", - "semver": "^7.5.4" + "@typescript-eslint/scope-manager": "7.9.0", + "@typescript-eslint/types": "7.9.0", + "@typescript-eslint/typescript-estree": "7.9.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -518,16 +503,16 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", - "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz", + "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.1", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "7.9.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -1121,6 +1106,15 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/eslint/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1875,9 +1869,9 @@ } }, "node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -2729,9 +2723,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", - "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "engines": { "node": ">=16" @@ -2777,6 +2771,32 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.9.0.tgz", + "integrity": "sha512-7iTn9c10teHHCys5Ud/yaJntXZrjt3h2mrx3feJGBOLgQkF3TB1X89Xs3aVQ/GgdXRAXpk2bPTdpRwHP4YkUow==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "7.9.0", + "@typescript-eslint/parser": "7.9.0", + "@typescript-eslint/utils": "7.9.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", diff --git a/vscode-ext/package.json b/vscode-ext/package.json index e6c4418..a33fe96 100644 --- a/vscode-ext/package.json +++ b/vscode-ext/package.json @@ -139,21 +139,23 @@ "compile": "tsc -p ./", "watch": "tsc -watch -p ./", "pretest": "npm run compile && npm run lint", - "lint": "eslint src --ext ts", + "lint": "eslint src", "test": "vscode-test" }, "devDependencies": { - "@types/vscode": "^1.87.0", + "@eslint/js": "^9.2.0", "@types/mocha": "^10.0.6", "@types/node": "18.x", + "@types/vscode": "^1.87.0", "@typescript-eslint/eslint-plugin": "^7.0.2", "@typescript-eslint/parser": "^7.0.2", + "@vscode/test-cli": "^0.0.6", + "@vscode/test-electron": "^2.3.9", "eslint": "^8.56.0", "typescript": "^5.3.3", - "@vscode/test-cli": "^0.0.6", - "@vscode/test-electron": "^2.3.9" + "typescript-eslint": "^7.9.0" }, "dependencies": { - "vscode-languageclient": "9.0.1" + "vscode-languageclient": "^9.0.1" } } diff --git a/vscode-ext/src/CaesarClient.ts b/vscode-ext/src/CaesarClient.ts index 49f5472..b71c98d 100644 --- a/vscode-ext/src/CaesarClient.ts +++ b/vscode-ext/src/CaesarClient.ts @@ -4,8 +4,8 @@ import { ExtensionContext, Range, TextDocument } from "vscode"; import * as vscode from "vscode"; import { ConfigurationConstants } from "./constants"; import { ServerConfig } from "./Configuration"; -import path from "path"; -import fs from 'fs'; +import * as path from "path"; +import * as fs from 'fs'; export enum ServerStatus { Stopped, @@ -63,7 +63,7 @@ export class CaesarClient { /// Try to initialize the client and return the client if successful otherwise return null private initialize(context: ExtensionContext): LanguageClient | null { try { - this.client = this.create_client(context); + this.client = this.createClient(context); } catch (error) { this.notifyStatusUpdate(ServerStatus.FailedToStart); vscode.window.showErrorMessage("Failed to initialize Caesar") @@ -74,7 +74,7 @@ export class CaesarClient { return this.client; } - private create_client(context: vscode.ExtensionContext): LanguageClient { + private createClient(context: vscode.ExtensionContext): LanguageClient { // Get the source code / binary path from the configurations let serverPath: string = ServerConfig.get(ConfigurationConstants.installationPath); if (serverPath === "") { diff --git a/vscode-ext/tsconfig.json b/vscode-ext/tsconfig.json index f959226..d64072f 100644 --- a/vscode-ext/tsconfig.json +++ b/vscode-ext/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "module": "Node16", + "module": "CommonJS", "target": "ES2022", "outDir": "out", "lib": [ From a120b20945a5cf108755aaa4fe3dde780e79cf7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Schro=CC=88er?= Date: Tue, 14 May 2024 19:10:57 +0200 Subject: [PATCH 25/25] vscode-ext: eslint is now happy --- .vscode/settings.json | 2 +- vscode-ext/.eslintignore | 3 -- vscode-ext/eslint.config.mjs | 14 +++-- vscode-ext/package.json | 2 +- vscode-ext/src/CaesarClient.ts | 71 ++++++++++++------------- vscode-ext/src/ComputedPreComponent.ts | 26 ++++----- vscode-ext/src/Configuration.ts | 2 +- vscode-ext/src/GutterStatusComponent.ts | 26 ++++----- vscode-ext/src/Verifier.ts | 6 +-- vscode-ext/src/extension.ts | 8 +-- vscode-ext/src/test/extension.test.ts | 2 +- vscode-ext/tsconfig.json | 1 - 12 files changed, 81 insertions(+), 82 deletions(-) delete mode 100644 vscode-ext/.eslintignore diff --git a/.vscode/settings.json b/.vscode/settings.json index 5c5a2bf..b073386 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,7 +8,7 @@ // Turn off tsc task auto detection since we have the necessary tasks as npm scripts "typescript.tsc.autoDetect": "off", "eslint.workingDirectories": [ - "vscode-ext" + "./vscode-ext" ], "eslint.experimental.useFlatConfig": true } \ No newline at end of file diff --git a/vscode-ext/.eslintignore b/vscode-ext/.eslintignore deleted file mode 100644 index 224ecd9..0000000 --- a/vscode-ext/.eslintignore +++ /dev/null @@ -1,3 +0,0 @@ -out/**/* -dist/**/* -**/*.d.ts \ No newline at end of file diff --git a/vscode-ext/eslint.config.mjs b/vscode-ext/eslint.config.mjs index 79270b3..983b0b4 100644 --- a/vscode-ext/eslint.config.mjs +++ b/vscode-ext/eslint.config.mjs @@ -8,7 +8,7 @@ export default tseslint.config( { "languageOptions": { "parserOptions": { - "project": "tsconfig.json", + "project": "./tsconfig.json", tsconfigRootDir: import.meta.dirname, "ecmaVersion": 6, "sourceType": "module" @@ -37,6 +37,14 @@ export default tseslint.config( "no-throw-literal": "warn", "semi": "off", "@typescript-eslint/no-floating-promises": "error", - "@typescript-eslint/no-explicit-any": "off" + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-unsafe-assignment": "off" }, - }); \ No newline at end of file + }, { + ignores: [ + "eslint.config.mjs", + ".vscode-text.mjs", + "out/", + ".vscode-test.mjs" + ] +}); \ No newline at end of file diff --git a/vscode-ext/package.json b/vscode-ext/package.json index a33fe96..4ba6693 100644 --- a/vscode-ext/package.json +++ b/vscode-ext/package.json @@ -139,7 +139,7 @@ "compile": "tsc -p ./", "watch": "tsc -watch -p ./", "pretest": "npm run compile && npm run lint", - "lint": "eslint src", + "lint": "eslint .", "test": "vscode-test" }, "devDependencies": { diff --git a/vscode-ext/src/CaesarClient.ts b/vscode-ext/src/CaesarClient.ts index b71c98d..a8e9237 100644 --- a/vscode-ext/src/CaesarClient.ts +++ b/vscode-ext/src/CaesarClient.ts @@ -22,23 +22,23 @@ export enum VerifyResult { Unknown = "unknown" } -export type VerifyStatusNotification = { +export interface VerifyStatusNotification { document: VersionedTextDocumentIdentifier; - statuses: Array<[vscode.Range, VerifyResult]>; -}; + statuses: [vscode.Range, VerifyResult][]; +} -export type ComputedPreNotification = { +export interface ComputedPreNotification { document: VersionedTextDocumentIdentifier; - pres: Array<[vscode.Range, string]>; -}; + pres: [vscode.Range, string][]; +} export class CaesarClient { private client: LanguageClient | null; private context: ExtensionContext; - private statusListeners: Array<(status: ServerStatus) => void> = new Array(); - private updateListeners: Array<(document: TextDocumentIdentifier, results: Array<[Range, VerifyResult]>) => void> = new Array(); - private computedPreListeners: Array<(document: TextDocumentIdentifier, results: Array<[Range, string]>) => void> = new Array(); + private statusListeners = new Array<(status: ServerStatus) => void>(); + private updateListeners = new Array<(document: TextDocumentIdentifier, results: [Range, VerifyResult][]) => void>(); + private computedPreListeners = new Array<(document: TextDocumentIdentifier, results: [Range, string][]) => void>(); constructor(context: ExtensionContext) { @@ -66,8 +66,8 @@ export class CaesarClient { this.client = this.createClient(context); } catch (error) { this.notifyStatusUpdate(ServerStatus.FailedToStart); - vscode.window.showErrorMessage("Failed to initialize Caesar") - console.error(error) + void vscode.window.showErrorMessage("Failed to initialize Caesar"); + console.error(error); this.client = null; } @@ -76,10 +76,10 @@ export class CaesarClient { private createClient(context: vscode.ExtensionContext): LanguageClient { // Get the source code / binary path from the configurations - let serverPath: string = ServerConfig.get(ConfigurationConstants.installationPath); + const serverPath: string = ServerConfig.get(ConfigurationConstants.installationPath); if (serverPath === "") { - vscode.window.showErrorMessage("Caesar: Installation path is not set. Please set the path in the settings.") - throw new Error("Installation path is not set") + void vscode.window.showErrorMessage("Caesar: Installation path is not set. Please set the path in the settings."); + throw new Error("Installation path is not set"); } let serverExecutable = ""; let args: string[] = []; @@ -90,8 +90,8 @@ export class CaesarClient { break; case ConfigurationConstants.sourceCodeOption: if (!fs.existsSync(path.resolve(serverPath, "Cargo.toml"))) { - vscode.window.showErrorMessage("Caesar: Cargo.toml file is not found in the path. Please check the path in the settings.") - throw new Error("Cargo.toml file is not found in the path") + void vscode.window.showErrorMessage("Caesar: Cargo.toml file is not found in the path. Please check the path in the settings."); + throw new Error("Cargo.toml file is not found in the path"); } serverExecutable = "cargo"; args = ['run', '--', '--language-server']; @@ -100,7 +100,7 @@ export class CaesarClient { // If the extension is launched in debug mode then the debug server options are used // Otherwise the run options are used - let serverOptions: ServerOptions = { + const serverOptions: ServerOptions = { run: { command: serverExecutable, args: args, @@ -123,7 +123,7 @@ export class CaesarClient { }; // Options to control the language client - let clientOptions: LanguageClientOptions = { + const clientOptions: LanguageClientOptions = { diagnosticCollectionName: 'caesar', // Register the server for heyvl documents documentSelector: [{ scheme: 'file', language: 'heyvl' }], @@ -133,24 +133,24 @@ export class CaesarClient { } }; - let client = new LanguageClient( + const client = new LanguageClient( 'caesar', 'Caesar', serverOptions, clientOptions ); - context.subscriptions.push(client) + context.subscriptions.push(client); // set up listeners for our custom events context.subscriptions.push(client.onNotification("custom/verifyStatus", (params: VerifyStatusNotification) => { - for (let listener of this.updateListeners) { + for (const listener of this.updateListeners) { listener(params.document, params.statuses); } })); context.subscriptions.push(client.onNotification("custom/computedPre", (params: ComputedPreNotification) => { - for (let listener of this.computedPreListeners) { + for (const listener of this.computedPreListeners) { listener(params.document, params.pres); } })); @@ -159,15 +159,15 @@ export class CaesarClient { context.subscriptions.push(vscode.workspace.onDidSaveTextDocument((document) => { // TODO: look at setting if (document.languageId !== "heyvl") { - return + return; } - this.verify(document); + void this.verify(document); })); vscode.commands.registerCommand('caesar.verify', async () => { - let openEditor = vscode.window.activeTextEditor; + const openEditor = vscode.window.activeTextEditor; if (openEditor) { - this.verify(openEditor.document); + await this.verify(openEditor.document); } }); return client; @@ -180,7 +180,7 @@ export class CaesarClient { if (this.client === null) { // First initialize the client by creating a new one, if it fails return if (this.initialize(this.context) === null) { - return + return; }; } await this.client!.start(); @@ -190,25 +190,24 @@ export class CaesarClient { async restart() { if (this.client === null) { - this.start() - return + await this.start(); } else { console.log("Restarting Caesar"); - this.client?.restart(); + await this.client?.restart(); } } async stop() { console.log("Stopping Caesar"); - this.client?.stop(); + await this.client?.stop(); this.notifyStatusUpdate(ServerStatus.Stopped); } async verify(document: TextDocument) { if (this.client === null) { - return + return; } - let documentItem = { + const documentItem = { uri: document.uri.toString(), languageId: document.languageId, version: document.version, @@ -225,16 +224,16 @@ export class CaesarClient { } private notifyStatusUpdate(status: ServerStatus) { - for (let listener of this.statusListeners) { + for (const listener of this.statusListeners) { listener(status); } } - public onVerifyResult(callback: (document: TextDocumentIdentifier, results: Array<[Range, VerifyResult]>) => void) { + public onVerifyResult(callback: (document: TextDocumentIdentifier, results: [Range, VerifyResult][]) => void) { this.updateListeners.push(callback); } - public onComputedPre(callback: (document: TextDocumentIdentifier, results: Array<[Range, string]>) => void) { + public onComputedPre(callback: (document: TextDocumentIdentifier, results: [Range, string][]) => void) { this.computedPreListeners.push(callback); } } diff --git a/vscode-ext/src/ComputedPreComponent.ts b/vscode-ext/src/ComputedPreComponent.ts index a1a70d2..47c832c 100644 --- a/vscode-ext/src/ComputedPreComponent.ts +++ b/vscode-ext/src/ComputedPreComponent.ts @@ -7,7 +7,7 @@ import { DocumentMap, Verifier } from "./Verifier"; export class ComputedPreComponent { private enabled: boolean; - private computedPres: DocumentMap>; + private computedPres: DocumentMap<[Range, string][]>; private decorationType: TextEditorDecorationType; @@ -29,7 +29,7 @@ export class ComputedPreComponent { })); // render when visible text editors change - verifier.context.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors((_visibleEditors) => { + verifier.context.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors(() => { this.render(); })); @@ -40,8 +40,8 @@ export class ComputedPreComponent { // clear all information when a new verification task is started verifier.client.onStatusUpdate((status) => { - if (status == ServerStatus.Verifying) { - for (let [_document, results] of this.computedPres.entries()) { + if (status === ServerStatus.Verifying) { + for (const [_document, results] of this.computedPres.entries()) { results.length = 0; } this.render(); @@ -52,25 +52,25 @@ export class ComputedPreComponent { } render() { - let backgroundColor = new vscode.ThemeColor('caesar.inlineGhostBackgroundColor'); - let color = new vscode.ThemeColor('caesar.inlineGhostForegroundColor'); + const backgroundColor = new vscode.ThemeColor('caesar.inlineGhostBackgroundColor'); + const color = new vscode.ThemeColor('caesar.inlineGhostForegroundColor'); - for (let [document_id, pres] of this.computedPres.entries()) { - for (let editor of vscode.window.visibleTextEditors) { + for (const [document_id, pres] of this.computedPres.entries()) { + for (const editor of vscode.window.visibleTextEditors) { if (editor.document.uri.toString() !== document_id.uri) { continue; } - let decorations: vscode.DecorationOptions[] = []; + const decorations: vscode.DecorationOptions[] = []; if (this.enabled) { - for (let [range, text] of pres) { - let line = range.start.line; + for (const [range, text] of pres) { + const line = range.start.line; if (line === 0) { continue; } - let lineAbove = line - 1; - let rangeAbove = new vscode.Range(lineAbove, 0, lineAbove, 0); + const lineAbove = line - 1; + const rangeAbove = new vscode.Range(lineAbove, 0, lineAbove, 0); if (editor.document.lineAt(lineAbove).text.trim() === '') { decorations.push({ range: rangeAbove, diff --git a/vscode-ext/src/Configuration.ts b/vscode-ext/src/Configuration.ts index 808d42f..91d90cb 100644 --- a/vscode-ext/src/Configuration.ts +++ b/vscode-ext/src/Configuration.ts @@ -6,7 +6,7 @@ export default class Configuration { /// Get a configuration value from the configuration file with the given key public static get(key: string): any { - const val = vscode.workspace.getConfiguration(CONFIGURATION_SECTION).get(key) + const val = vscode.workspace.getConfiguration(CONFIGURATION_SECTION).get(key); if (val === undefined) { throw new Error(`${key} is not defined in the configuration file`); } diff --git a/vscode-ext/src/GutterStatusComponent.ts b/vscode-ext/src/GutterStatusComponent.ts index 2498aac..d848ec0 100644 --- a/vscode-ext/src/GutterStatusComponent.ts +++ b/vscode-ext/src/GutterStatusComponent.ts @@ -1,13 +1,13 @@ import { Range } from "vscode"; import * as vscode from 'vscode'; -import { CONFIGURATION_SECTION, GutterInformationViewConfig, StatusBarViewConfig } from "./Configuration"; +import { CONFIGURATION_SECTION, GutterInformationViewConfig } from "./Configuration"; import { ServerStatus, VerifyResult } from "./CaesarClient"; import { DocumentMap, Verifier } from "./Verifier"; export class GutterStatusComponent { private enabled: boolean; - private status: DocumentMap>; + private status: DocumentMap<[Range, VerifyResult][]>; private verifyDecType: vscode.TextEditorDecorationType; private failedDecType: vscode.TextEditorDecorationType; @@ -33,14 +33,14 @@ export class GutterStatusComponent { })); // render when visible editors change - verifier.context.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors((_visibleEditors) => { + verifier.context.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors(() => { this.render(); })); // listen to status and verify updates verifier.client.onStatusUpdate((status) => { - if (status == ServerStatus.Verifying) { - for (let [_document, results] of this.status.entries()) { + if (status === ServerStatus.Verifying) { + for (const [_document, results] of this.status.entries()) { results.length = 0; } this.render(); @@ -54,20 +54,20 @@ export class GutterStatusComponent { } render() { - for (let [document_id, results] of this.status.entries()) { - for (let editor of vscode.window.visibleTextEditors) { + for (const [document_id, results] of this.status.entries()) { + for (const editor of vscode.window.visibleTextEditors) { if (editor.document.uri.toString() !== document_id.uri) { continue; } - let verifiedProcs: vscode.DecorationOptions[] = []; - let failedProcs: vscode.DecorationOptions[] = []; - let unknownProcs: vscode.DecorationOptions[] = []; + const verifiedProcs: vscode.DecorationOptions[] = []; + const failedProcs: vscode.DecorationOptions[] = []; + const unknownProcs: vscode.DecorationOptions[] = []; if (this.enabled) { - for (let [range, result] of results) { - let line = range.start.line; - let gutterRange = new vscode.Range(line, 0, line, 0); + for (const [range, result] of results) { + const line = range.start.line; + const gutterRange = new vscode.Range(line, 0, line, 0); switch (result) { case VerifyResult.Verified: verifiedProcs.push({ range: gutterRange, hoverMessage: 'Verified' }); diff --git a/vscode-ext/src/Verifier.ts b/vscode-ext/src/Verifier.ts index a5ac26a..eb91124 100644 --- a/vscode-ext/src/Verifier.ts +++ b/vscode-ext/src/Verifier.ts @@ -6,21 +6,21 @@ import { GutterStatusComponent } from "./GutterStatusComponent"; import { ComputedPreComponent } from "./ComputedPreComponent"; export class DocumentMap { - private map: Map = new Map(); + private map = new Map(); public insert(document_id: TextDocumentIdentifier, value: T) { this.map.set(document_id.uri.toString(), [document_id, value]); } public get(document_id: TextDocumentIdentifier): T | undefined { - let res = this.map.get(document_id.uri.toString()); + const res = this.map.get(document_id.uri.toString()); if (res !== undefined) { return res[1]; } return undefined; } - public entries(): Array<[TextDocumentIdentifier, T]> { + public entries(): [TextDocumentIdentifier, T][] { return Array.from(this.map.values()); } } diff --git a/vscode-ext/src/extension.ts b/vscode-ext/src/extension.ts index 76de5ca..f81c591 100644 --- a/vscode-ext/src/extension.ts +++ b/vscode-ext/src/extension.ts @@ -8,12 +8,8 @@ import { ConfigurationConstants } from './constants'; // This method is called when your extension is activated // Your extension is activated the very first time the command is executed export function activate(context: vscode.ExtensionContext) { - let verifier = new Verifier(context); + const verifier = new Verifier(context); if (ServerConfig.get(ConfigurationConstants.autoStartServer)) { - verifier.start(); + void verifier.start(); } } - -// This method is called when the extension is deactivated -export function deactivate() { } - diff --git a/vscode-ext/src/test/extension.test.ts b/vscode-ext/src/test/extension.test.ts index 4ca0ab4..cc7ab30 100644 --- a/vscode-ext/src/test/extension.test.ts +++ b/vscode-ext/src/test/extension.test.ts @@ -6,7 +6,7 @@ import * as vscode from 'vscode'; // import * as myExtension from '../../extension'; suite('Extension Test Suite', () => { - vscode.window.showInformationMessage('Start all tests.'); + void vscode.window.showInformationMessage('Start all tests.'); test('Sample test', () => { assert.strictEqual(-1, [1, 2, 3].indexOf(5)); diff --git a/vscode-ext/tsconfig.json b/vscode-ext/tsconfig.json index d64072f..5a2d648 100644 --- a/vscode-ext/tsconfig.json +++ b/vscode-ext/tsconfig.json @@ -13,6 +13,5 @@ "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ "noUnusedParameters": true, /* Report errors on unused parameters. */ - } }