diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..2fd569f --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,33 @@ +name: Verify +on: + pull_request: + branches: [dev] + push: + branches: [dev] +permissions: + contents: read +concurrency: + group: verify-${{ github.ref }} + cancel-in-progress: true +jobs: + packages: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 + with: + persist-credentials: false + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 + with: + node-version: 22 + package-manager-cache: false + - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 + with: + bun-version: 1.4.0 + - name: Prepare pinned Rust toolchain + run: rustup toolchain install 1.93.1 --profile minimal --component rustfmt --target wasm32-wasip2 + - run: bun install --frozen-lockfile + - run: bun run verify + - name: Package VS Code + run: | + mkdir -p artifacts + bun run --cwd vscode package -- --out ../artifacts/rootform.vsix diff --git a/README.md b/README.md index f48ec9f..938705f 100644 --- a/README.md +++ b/README.md @@ -17,3 +17,7 @@ the clients only own syntax presentation, launch and lifecycle. Source is [Apache-2.0](LICENSE). Third-party syntax dependencies retain their original licenses. + +Native editor runtime qualification currently covers macOS arm64. The Zed +package also builds for `wasm32-wasip2`; Linux and Windows editor runtimes have +not yet been qualified. diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..5de61ef --- /dev/null +++ b/biome.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.5.14/schema.json", + "files": { + "includes": [ + "**", + "!vscode/dist/**", + "!vscode/out/**", + "!zed/target/**", + "!zed/grammars/**", + "!artifacts/**" + ] + }, + "formatter": { "indentStyle": "space", "indentWidth": 2, "lineWidth": 100 }, + "linter": { "enabled": false } +} diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..3ec1879 --- /dev/null +++ b/bun.lock @@ -0,0 +1,441 @@ +{ + "lockfileVersion": 2, + "configVersion": 1, + "workspaces": { + "": { + "name": "@rootform/editors-repository", + "devDependencies": { + "@biomejs/biome": "2.5.14", + "@types/bun": "1.4.0", + }, + }, + "vscode": { + "name": "rootform", + "version": "0.1.0", + "dependencies": { + "vscode-languageclient": "10.1.2", + }, + "devDependencies": { + "@types/node": "22.20.4", + "@types/vscode": "1.91.0", + "@vscode/test-electron": "3.1.0", + "@vscode/vsce": "4.0.0", + "typescript": "7.0.2", + }, + }, + }, + "patchedDependencies": { + "vscode-languageclient@10.1.2": "patches/vscode-languageclient@10.1.2.patch", + }, + "packages": { + "@azure/abort-controller": ["@azure/abort-controller@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-fNAjWnA/nZ2jz31kxR/AqRaUT8ewHBw/WuBIosK0moMy1C9e5ValbDfFdIxJzVOOYaYkV/b2F1S4H/aHiqfVQg=="], + + "@azure/core-auth": ["@azure/core-auth@1.11.0", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-util": "^1.13.0", "tslib": "^2.6.2" } }, "sha512-IUZydyTUkDnYdstOW9pFOOUQlBjAepK5teihDE3x6yxsPJs/hsAaaYpeGxdxrgtOiJbBKSjKW7MDk7AEhb4LRg=="], + + "@azure/core-client": ["@azure/core-client@1.11.1", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.10.0", "@azure/core-rest-pipeline": "^1.22.0", "@azure/core-tracing": "^1.3.0", "@azure/core-util": "^1.13.0", "@azure/logger": "^1.3.0", "tslib": "^2.6.2" } }, "sha512-2QygG2F76ZpMP2eMztiJvAiFMu71M9rDeU7vO/QKg5Css7MgM4frUOslFjhVjRhbGaCNPtz/S8M6y46/fFKVuQ=="], + + "@azure/core-process": ["@azure/core-process@1.0.0", "", {}, "sha512-/shnJ+ooO8WPxDhPEeI/2oRQuubn16gZ6CvlbpWbEswZfzwI9tI/sMAHmF3x1LuQ9yZYXfLW3TjzGMLEC5blKg=="], + + "@azure/core-rest-pipeline": ["@azure/core-rest-pipeline@1.25.0", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.10.0", "@azure/core-tracing": "^1.3.0", "@azure/core-util": "^1.13.0", "@azure/logger": "^1.3.0", "@typespec/ts-http-runtime": "^0.3.4", "tslib": "^2.6.2" } }, "sha512-bMs8ekJLjX8wPV+9IPBges1SLPyuDtE9g5gLDWOpxzKcoOFQnpLGkbcT1tdw3FaAmDS1gnPmMmJ6y/T5B96kIA=="], + + "@azure/core-tracing": ["@azure/core-tracing@1.4.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-eGwxD0AtncrxeBM4tG8R55Pc3rdX1hNW2WibJAgYpCVA6E93mvvVH+LcssoVjOBrSKWS55yEIHsk0X8ctHmfOQ=="], + + "@azure/core-util": ["@azure/core-util@1.14.0", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@typespec/ts-http-runtime": "^0.3.0", "tslib": "^2.6.2" } }, "sha512-9n2pWK61veAuN0V20t9lOuoV4CFMdyAZ1ygZzvBGk/pBBJRib/PjL9PLXa/aI2CcPpyHfqVsxxqLCYl6uZlfDw=="], + + "@azure/identity": ["@azure/identity@4.13.3", "", { "dependencies": { "@azure/abort-controller": "^2.0.0", "@azure/core-auth": "^1.9.0", "@azure/core-client": "^1.9.2", "@azure/core-process": "^1.0.0", "@azure/core-rest-pipeline": "^1.17.0", "@azure/core-tracing": "^1.0.0", "@azure/core-util": "^1.11.0", "@azure/logger": "^1.0.0", "@azure/msal-browser": "^5.5.0", "@azure/msal-node": "^6.0.0", "open": "^10.1.0", "tslib": "^2.2.0" } }, "sha512-zGQPtqvXPgSA8yfV2CkIQ1qirqk0p9AIVpC5uEkdXQYcKl07QHvyaGYRnZOk0AsQUmxNb4wfkcwY5di8Z5xa9A=="], + + "@azure/logger": ["@azure/logger@1.4.0", "", { "dependencies": { "@typespec/ts-http-runtime": "^0.3.0", "tslib": "^2.6.2" } }, "sha512-rbAE25KUfjU/s3XHUdJgceoCP5dEOpMx85J04kF+QMdta73XkuG9JGHHinch+XIoKpBdqljin+KqURpJriSzLA=="], + + "@azure/msal-browser": ["@azure/msal-browser@5.23.0", "", { "dependencies": { "@azure/msal-common": "16.14.1" } }, "sha512-IRCwkRCK47hBXK+7bu67UZWY7HS0Jx1dZgi4C1HVbjlBum8Jy8fb2l87xFr6HxdQJWy951zRUHtwwDITHFAtaA=="], + + "@azure/msal-common": ["@azure/msal-common@16.14.1", "", {}, "sha512-Or6xhPNyi4zHW25158yxBoyxuCqNSPa5YBVqfF1J5Ks4MJWBo/USXdp05DQIPu1Zli00YZu6t0+h6KvHJealxQ=="], + + "@azure/msal-node": ["@azure/msal-node@6.0.1", "", { "dependencies": { "@azure/msal-common": "16.14.1", "jsonwebtoken": "^9.0.0" } }, "sha512-ixSO1Y/kCVRthRs+hSx/5qkwaunX1/RAePhlMN0wIpIQ4WEZ6AREGGnGd1AP0qspHVsAwzWQKGubpjh50JyJIQ=="], + + "@biomejs/biome": ["@biomejs/biome@2.5.14", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.5.14", "@biomejs/cli-darwin-x64": "2.5.14", "@biomejs/cli-linux-arm64": "2.5.14", "@biomejs/cli-linux-arm64-musl": "2.5.14", "@biomejs/cli-linux-x64": "2.5.14", "@biomejs/cli-linux-x64-musl": "2.5.14", "@biomejs/cli-win32-arm64": "2.5.14", "@biomejs/cli-win32-x64": "2.5.14" }, "bin": { "biome": "bin/biome" } }, "sha512-0FabLIjd4M/dm8VFI86RMaLLdgepzbdfiAL2R8cr7V81OYYrP1w7Z73KfAwPK5h9SrEBXTzNG2y+mBwPo9xRnw=="], + + "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.5.14", "", { "os": "darwin", "cpu": "arm64" }, "sha512-UnzaXO65L4tsZimFITFP2M121GyhDcWFrT3pL5ZJ5U4XcS/0L5VHYytVohdCf/gnDUFHgl2I9xnt5bV/J1kxHQ=="], + + "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.5.14", "", { "os": "darwin", "cpu": "x64" }, "sha512-kiy8qA16K93J7uvFfWi4LgjqDpnRKyePAna6A0Y4jxyUga35SYpIZ2cNWlhy0lsfgqRenCpfymnJWEZ6mgpRgA=="], + + "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.5.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-vO/9BaU1n30CiFNLx49gMTMtbCAAqlo/EqFoG0BU3deQInTbJrmXSmTQ9e3FoDZIKQnvSLDVNL4lx1ci7y1T1Q=="], + + "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.5.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-SJ9PrZkBnnH9dHJDnxk34vKs0GB2dbsioaft6/hPhWJ7AHpwYH83Isnhj0FSRpFkGgpVfJ1lds23ApB2czUDLQ=="], + + "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.5.14", "", { "os": "linux", "cpu": "x64" }, "sha512-VHZRa7CCQBUWKxNwUvHJeuW03WFRgN5NWO//SDGOitc9QIeNyfA42V9zlKm+x82xFSG9Bzi5fi+hbhm9anO8yA=="], + + "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.5.14", "", { "os": "linux", "cpu": "x64" }, "sha512-2kI5PrMgW5dcEZYrstLPmUmCwkUwZY39rP4BN93Vxbwcs2O57LDQOktUZZYPvvspN5i0mhGr3TJtF5sU26NUWg=="], + + "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.5.14", "", { "os": "win32", "cpu": "arm64" }, "sha512-pHgAFffmZtaYoxavEsWEYNvcA7NwOIjLyqw2HXyLbt16xYryX0L4fMV2u0G9ag6LNYPIoqWaWqzUcnc6rLGGXg=="], + + "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.5.14", "", { "os": "win32", "cpu": "x64" }, "sha512-oJWmBhoHsnhUKIke+0gXDX0mltJrWHA1UyHsrTlXwX0TL64ilVZAo+TYZm97baecV0esBdpzy3k96q+09JaZUQ=="], + + "@napi-rs/keyring": ["@napi-rs/keyring@1.3.0", "", { "optionalDependencies": { "@napi-rs/keyring-darwin-arm64": "1.3.0", "@napi-rs/keyring-darwin-x64": "1.3.0", "@napi-rs/keyring-freebsd-x64": "1.3.0", "@napi-rs/keyring-linux-arm-gnueabihf": "1.3.0", "@napi-rs/keyring-linux-arm64-gnu": "1.3.0", "@napi-rs/keyring-linux-arm64-musl": "1.3.0", "@napi-rs/keyring-linux-riscv64-gnu": "1.3.0", "@napi-rs/keyring-linux-x64-gnu": "1.3.0", "@napi-rs/keyring-linux-x64-musl": "1.3.0", "@napi-rs/keyring-win32-arm64-msvc": "1.3.0", "@napi-rs/keyring-win32-ia32-msvc": "1.3.0", "@napi-rs/keyring-win32-x64-msvc": "1.3.0" } }, "sha512-WrOw/bcXm0f9qHkumlT1QlArXSTWqaY9sunsDpOk+yCCorCKMxvWT/a3xko4EYHVdeZoh00yI2TydXn6eyICDA=="], + + "@napi-rs/keyring-darwin-arm64": ["@napi-rs/keyring-darwin-arm64@1.3.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-pl76hJvdYUBn6I24bXiOBMA9nbDapo3I5B+f3OorjDU4dUMSypXeKbOVehJe8fhgTiH24flMyTS3aAIy43xegQ=="], + + "@napi-rs/keyring-darwin-x64": ["@napi-rs/keyring-darwin-x64@1.3.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-YcJtEV5LA3cvA4z3BurgxH5IhTsW1JfIvcAAcqcecwk06Si9F9NqkxbZVIfDwQ8oRHgaBmT3zZJnLAotCrVahw=="], + + "@napi-rs/keyring-freebsd-x64": ["@napi-rs/keyring-freebsd-x64@1.3.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-vlLf31TGhfRAaxLDBhg8b89ss0HHD/lyNmL5F3UjSaz5CUXElsJmKYq9fqA/B+cZKUEUcLHHGhF0I/CqcFdaVw=="], + + "@napi-rs/keyring-linux-arm-gnueabihf": ["@napi-rs/keyring-linux-arm-gnueabihf@1.3.0", "", { "os": "linux", "cpu": "arm" }, "sha512-KiWdMMu/Inz/bHHIAGrnF7r54FZDYXuHO6UFF/rhIrshUsxbMG1Rl9lEymNtqqsVo927G0VYcb02FzWQ3iBQRQ=="], + + "@napi-rs/keyring-linux-arm64-gnu": ["@napi-rs/keyring-linux-arm64-gnu@1.3.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-eyKGpY40lm9Jvs1aD294XRH4y7+TlJM0YVAryZeXA6TX0mb4gMkxVXwSQv7MCwgah7raeUd0dKUb4BPAYIgcMg=="], + + "@napi-rs/keyring-linux-arm64-musl": ["@napi-rs/keyring-linux-arm64-musl@1.3.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-iIK6JWHXAJqDrEyLY3TmswwloVyt2vj+04TZnew+uSJ9gnDO8EwRbp3/iw3LpWaXiDO7VomGO6y8I0Id8uBZSw=="], + + "@napi-rs/keyring-linux-riscv64-gnu": ["@napi-rs/keyring-linux-riscv64-gnu@1.3.0", "", { "os": "linux", "cpu": "none" }, "sha512-/PGqrwn6EwgtK6vccASSXJRfOSP4vN1F4ASsIQ+7MdrK6hNvAJ1FZPrIuD5gGGdxezo3F++To2Wq7DbuGIeuNQ=="], + + "@napi-rs/keyring-linux-x64-gnu": ["@napi-rs/keyring-linux-x64-gnu@1.3.0", "", { "os": "linux", "cpu": "x64" }, "sha512-2PDK1WKWTu9lBGq9VvNEkSlQD3O7YwVpmnyN2M3cy4v7NJ/8gDMd9GXv3G+FVXN13uhp4gnnPBS+ScefmEeD2A=="], + + "@napi-rs/keyring-linux-x64-musl": ["@napi-rs/keyring-linux-x64-musl@1.3.0", "", { "os": "linux", "cpu": "x64" }, "sha512-oJ2HkX8YUo46QBkn0pG+HuIKQNqr523q6vBobCn+P95s4C4K6/kLBqHY/1bg5J4ap31DzsznhnFKcfBNBsjCnw=="], + + "@napi-rs/keyring-win32-arm64-msvc": ["@napi-rs/keyring-win32-arm64-msvc@1.3.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-tOd3c/uAaeoE4ycVlmAdSvygz0Zt3zdca6Y7gokBeIbaRDWpjDIUOpU3MvML59XAaqyuKGsVVu0F/DZb1lHPmw=="], + + "@napi-rs/keyring-win32-ia32-msvc": ["@napi-rs/keyring-win32-ia32-msvc@1.3.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-sPSqeAFZMGqP1R++M2JTza7GQJJ/TpCo6JU6Vcd4jnebvOaEDs9b7eipakU1PJdSvhpC2yXMCNRk9gXfrhuwHQ=="], + + "@napi-rs/keyring-win32-x64-msvc": ["@napi-rs/keyring-win32-x64-msvc@1.3.0", "", { "os": "win32", "cpu": "x64" }, "sha512-4DnCWXwDc0HRKwyRlG5y0VhKZW2tNRQfKKfyj6IX/KWfDNyq9hn4n+GL1auyDcOO/v8PwnhmYo2+rOOqCkvvOg=="], + + "@secretlint/core": ["@secretlint/core@10.2.2", "", { "dependencies": { "@secretlint/profiler": "^10.2.2", "@secretlint/types": "^10.2.2", "debug": "^4.4.1", "structured-source": "^4.0.0" } }, "sha512-6rdwBwLP9+TO3rRjMVW1tX+lQeo5gBbxl1I5F8nh8bgGtKwdlCMhMKsBWzWg1ostxx/tIG7OjZI0/BxsP8bUgw=="], + + "@secretlint/profiler": ["@secretlint/profiler@10.2.2", "", {}, "sha512-qm9rWfkh/o8OvzMIfY8a5bCmgIniSpltbVlUVl983zDG1bUuQNd1/5lUEeWx5o/WJ99bXxS7yNI4/KIXfHexig=="], + + "@secretlint/secretlint-rule-no-dotenv": ["@secretlint/secretlint-rule-no-dotenv@10.2.2", "", { "dependencies": { "@secretlint/types": "^10.2.2" } }, "sha512-KJRbIShA9DVc5Va3yArtJ6QDzGjg3PRa1uYp9As4RsyKtKSSZjI64jVca57FZ8gbuk4em0/0Jq+uy6485wxIdg=="], + + "@secretlint/secretlint-rule-preset-recommend": ["@secretlint/secretlint-rule-preset-recommend@10.2.2", "", {}, "sha512-K3jPqjva8bQndDKJqctnGfwuAxU2n9XNCPtbXVI5JvC7FnQiNg/yWlQPbMUlBXtBoBGFYp08A94m6fvtc9v+zA=="], + + "@secretlint/source-creator": ["@secretlint/source-creator@10.2.2", "", { "dependencies": { "@secretlint/types": "^10.2.2", "istextorbinary": "^9.5.0" } }, "sha512-h6I87xJfwfUTgQ7irWq7UTdq/Bm1RuQ/fYhA3dtTIAop5BwSFmZyrchph4WcoEvbN460BWKmk4RYSvPElIIvxw=="], + + "@secretlint/types": ["@secretlint/types@10.2.2", "", {}, "sha512-Nqc90v4lWCXyakD6xNyNACBJNJ0tNCwj2WNk/7ivyacYHxiITVgmLUFXTBOeCdy79iz6HtN9Y31uw/jbLrdOAg=="], + + "@types/bun": ["@types/bun@1.4.0", "", { "dependencies": { "bun-types": "1.4.0" } }, "sha512-K+lZULY23vRgK/CfTjFIV+tyifaNdSMlPh9j+6mQ/cLfpOznLyAuzgV/JQysyECpkBQLVMSyvjlr2fBUSA9wFQ=="], + + "@types/node": ["@types/node@22.20.4", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-zJRE40jpHtKqE/C4fgHrAKQLJuSpzEnP9ff9Y7YtoR3Wd2pwqzlekDeEuUQXjRd+QCYnVnNwuJYmhdk9XV8gvA=="], + + "@types/vscode": ["@types/vscode@1.91.0", "", {}, "sha512-PgPr+bUODjG3y+ozWUCyzttqR9EHny9sPAfJagddQjDwdtf66y2sDKJMnFZRuzBA2YtBGASqJGPil8VDUPvO6A=="], + + "@typescript/typescript-aix-ppc64": ["@typescript/typescript-aix-ppc64@7.0.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ=="], + + "@typescript/typescript-darwin-arm64": ["@typescript/typescript-darwin-arm64@7.0.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA=="], + + "@typescript/typescript-darwin-x64": ["@typescript/typescript-darwin-x64@7.0.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA=="], + + "@typescript/typescript-freebsd-arm64": ["@typescript/typescript-freebsd-arm64@7.0.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ=="], + + "@typescript/typescript-freebsd-x64": ["@typescript/typescript-freebsd-x64@7.0.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw=="], + + "@typescript/typescript-linux-arm": ["@typescript/typescript-linux-arm@7.0.2", "", { "os": "linux", "cpu": "arm" }, "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ=="], + + "@typescript/typescript-linux-arm64": ["@typescript/typescript-linux-arm64@7.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ=="], + + "@typescript/typescript-linux-loong64": ["@typescript/typescript-linux-loong64@7.0.2", "", { "os": "linux", "cpu": "none" }, "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ=="], + + "@typescript/typescript-linux-mips64el": ["@typescript/typescript-linux-mips64el@7.0.2", "", { "os": "linux", "cpu": "none" }, "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA=="], + + "@typescript/typescript-linux-ppc64": ["@typescript/typescript-linux-ppc64@7.0.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA=="], + + "@typescript/typescript-linux-riscv64": ["@typescript/typescript-linux-riscv64@7.0.2", "", { "os": "linux", "cpu": "none" }, "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ=="], + + "@typescript/typescript-linux-s390x": ["@typescript/typescript-linux-s390x@7.0.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw=="], + + "@typescript/typescript-linux-x64": ["@typescript/typescript-linux-x64@7.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A=="], + + "@typescript/typescript-netbsd-arm64": ["@typescript/typescript-netbsd-arm64@7.0.2", "", { "os": "none", "cpu": "arm64" }, "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA=="], + + "@typescript/typescript-netbsd-x64": ["@typescript/typescript-netbsd-x64@7.0.2", "", { "os": "none", "cpu": "x64" }, "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA=="], + + "@typescript/typescript-openbsd-arm64": ["@typescript/typescript-openbsd-arm64@7.0.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ=="], + + "@typescript/typescript-openbsd-x64": ["@typescript/typescript-openbsd-x64@7.0.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg=="], + + "@typescript/typescript-sunos-x64": ["@typescript/typescript-sunos-x64@7.0.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g=="], + + "@typescript/typescript-win32-arm64": ["@typescript/typescript-win32-arm64@7.0.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ=="], + + "@typescript/typescript-win32-x64": ["@typescript/typescript-win32-x64@7.0.2", "", { "os": "win32", "cpu": "x64" }, "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g=="], + + "@typespec/ts-http-runtime": ["@typespec/ts-http-runtime@0.3.9", "", { "dependencies": { "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "tslib": "^2.6.2" } }, "sha512-edSdeAqkdxBVzA1yL1LrLCml1YjyCVvPMtMqJpbF+6K609tHe8V6sQUzFQSGcYNhcuhOceZtjvN32+mpIth30A=="], + + "@vscode/test-electron": ["@vscode/test-electron@3.1.0", "", { "dependencies": { "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.5", "jszip": "^3.10.1", "ora": "^8.1.0", "semver": "^7.6.2" } }, "sha512-CRqv5u+YYoseuNVJ6Tyo4k0sF0mx4qnKMihRB0PjsUF8Dc0WKtCXo6CNL6nWWm5esfFQsQA/pejMj4ZbpJVLTw=="], + + "@vscode/vsce": ["@vscode/vsce@4.0.0", "", { "dependencies": { "@azure/identity": "^4.13.2", "@napi-rs/keyring": "^1.3.0", "@secretlint/core": "^10.2.2", "@secretlint/secretlint-rule-no-dotenv": "^10.2.2", "@secretlint/secretlint-rule-preset-recommend": "^10.2.2", "@secretlint/source-creator": "^10.2.2", "@secretlint/types": "^10.2.2", "@vscode/vsce-sign": "^2.1.0", "azure-devops-node-api": "^12.5.0", "cockatiel": "^3.2.1", "commander": "^12.1.0", "hosted-git-info": "^4.1.0", "jsonc-parser": "^3.3.1", "marked": "^18.0.11", "mime": "^1.6.0", "minimatch": "^10.2.6", "parse5": "^8.0.1", "proper-lockfile": "^4.1.2", "read": "^1.0.7", "semver": "^7.8.5", "tinyglobby": "^0.2.17", "typed-rest-client": "^1.8.11", "url-join": "^4.0.1", "xml2js": "^0.5.0", "yauzl": "^3.4.0", "yazl": "^2.5.1" }, "bin": { "vsce": "vsce" } }, "sha512-NImwuLaenMmb5D5Jer9/lzi/F9ZQUBOp8Azhj/BVYcTFgixv8KehFXqEUDjQlD2tAiw2E6dDGyjTuAB//di60A=="], + + "@vscode/vsce-sign": ["@vscode/vsce-sign@2.1.0", "", { "optionalDependencies": { "@vscode/vsce-sign-alpine-arm64": "2.0.6", "@vscode/vsce-sign-alpine-x64": "2.0.6", "@vscode/vsce-sign-darwin-arm64": "2.0.6", "@vscode/vsce-sign-darwin-x64": "2.0.6", "@vscode/vsce-sign-linux-arm": "2.0.6", "@vscode/vsce-sign-linux-arm64": "2.0.6", "@vscode/vsce-sign-linux-x64": "2.0.6", "@vscode/vsce-sign-win32-arm64": "2.0.6", "@vscode/vsce-sign-win32-x64": "2.0.6" } }, "sha512-9AQrqazrBgTgRSuwleLVXUrIUphY02/SFCh2TKYoLV/xifJAdblhdmEmw5gUrYSPQ3sRwNs9iyCMD14sATEE6g=="], + + "@vscode/vsce-sign-alpine-arm64": ["@vscode/vsce-sign-alpine-arm64@2.0.6", "", { "os": "none", "cpu": "arm64" }, "sha512-wKkJBsvKF+f0GfsUuGT0tSW0kZL87QggEiqNqK6/8hvqsXvpx8OsTEc3mnE1kejkh5r+qUyQ7PtF8jZYN0mo8Q=="], + + "@vscode/vsce-sign-alpine-x64": ["@vscode/vsce-sign-alpine-x64@2.0.6", "", { "os": "none", "cpu": "x64" }, "sha512-YoAGlmdK39vKi9jA18i4ufBbd95OqGJxRvF3n6ZbCyziwy3O+JgOpIUPxv5tjeO6gQfx29qBivQ8ZZTUF2Ba0w=="], + + "@vscode/vsce-sign-darwin-arm64": ["@vscode/vsce-sign-darwin-arm64@2.0.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-5HMHaJRIQuozm/XQIiJiA0W9uhdblwwl2ZNDSSAeXGO9YhB9MH5C4KIHOmvyjUnKy4UCuiP43VKpIxW1VWP4tQ=="], + + "@vscode/vsce-sign-darwin-x64": ["@vscode/vsce-sign-darwin-x64@2.0.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-25GsUbTAiNfHSuRItoQafXOIpxlYj+IXb4/qarrXu7kmbH94jlm5sdWSCKrrREs8+GsXF1b+l3OB7VJy5jsykw=="], + + "@vscode/vsce-sign-linux-arm": ["@vscode/vsce-sign-linux-arm@2.0.6", "", { "os": "linux", "cpu": "arm" }, "sha512-UndEc2Xlq4HsuMPnwu7420uqceXjs4yb5W8E2/UkaHBB9OWCwMd3/bRe/1eLe3D8kPpxzcaeTyXiK3RdzS/1CA=="], + + "@vscode/vsce-sign-linux-arm64": ["@vscode/vsce-sign-linux-arm64@2.0.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-cfb1qK7lygtMa4NUl2582nP7aliLYuDEVpAbXJMkDq1qE+olIw/es+C8j1LJwvcRq1I2yWGtSn3EkDp9Dq5FdA=="], + + "@vscode/vsce-sign-linux-x64": ["@vscode/vsce-sign-linux-x64@2.0.6", "", { "os": "linux", "cpu": "x64" }, "sha512-/olerl1A4sOqdP+hjvJ1sbQjKN07Y3DVnxO4gnbn/ahtQvFrdhUi0G1VsZXDNjfqmXw57DmPi5ASnj/8PGZhAA=="], + + "@vscode/vsce-sign-win32-arm64": ["@vscode/vsce-sign-win32-arm64@2.0.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-ivM/MiGIY0PJNZBoGtlRBM/xDpwbdlCWomUWuLmIxbi1Cxe/1nooYrEQoaHD8ojVRgzdQEUzMsRbyF5cJJgYOg=="], + + "@vscode/vsce-sign-win32-x64": ["@vscode/vsce-sign-win32-x64@2.0.6", "", { "os": "win32", "cpu": "x64" }, "sha512-mgth9Kvze+u8CruYMmhHw6Zgy3GRX2S+Ed5oSokDEK5vPEwGGKnmuXua9tmFhomeAnhgJnL4DCna3TiNuGrBTQ=="], + + "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], + + "ansi-regex": ["ansi-regex@6.4.0", "", {}, "sha512-KzTVk2tCWAHtYrvvvaP8bJKJq2pVinhLcGEQdtLIYPbmNGNyYe8QwNaTUYQp2J7/vIsUKt5QCqAfUkYyG9DkOw=="], + + "azure-devops-node-api": ["azure-devops-node-api@12.5.0", "", { "dependencies": { "tunnel": "0.0.6", "typed-rest-client": "^1.8.4" } }, "sha512-R5eFskGvOm3U/GzeAuxRkUsAl0hrAwGgWn6zAd2KrZmrEhWZVqLew4OOupbQlXUuojUzpGtq62SmdhJ06N88og=="], + + "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], + + "binaryextensions": ["binaryextensions@6.11.0", "", { "dependencies": { "editions": "^6.21.0" } }, "sha512-sXnYK/Ij80TO3lcqZVV2YgfKN5QjUWIRk/XSm2J/4bd/lPko3lvk0O4ZppH6m+6hB2/GTu+ptNwVFe1xh+QLQw=="], + + "boundary": ["boundary@2.0.0", "", {}, "sha512-rJKn5ooC9u8q13IMCrW0RSp31pxBCHE3y9V/tp3TdWSLf8Em3p6Di4NBpfzbJge9YjjFEsD0RtFEjtvHL5VyEA=="], + + "brace-expansion": ["brace-expansion@5.0.12", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ=="], + + "buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="], + + "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="], + + "bun-types": ["bun-types@1.4.0", "", { "dependencies": { "@types/node": "*" } }, "sha512-iIKw23BspnQQYd3prITOBxeUsxBHnwzX6YJfGMuNOZzeNcMmVqzIIVGRm1l69ogaPQmb4wB6BN8mA5bE9YuC5Q=="], + + "bundle-name": ["bundle-name@4.1.1", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-DdH81/zPLVS11EUgWq3tEu/xn+EzljlMYooDNdzWEnFha3R3NBMpMV1UqYIpjYHV/SgpFKMIX1Oh7o06SjM/oA=="], + + "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], + + "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], + + "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], + + "cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="], + + "cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="], + + "cockatiel": ["cockatiel@3.2.1", "", {}, "sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q=="], + + "commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], + + "core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="], + + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" }, "peerDependencies": { "supports-color": "*" }, "optionalPeers": ["supports-color"] }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "default-browser": ["default-browser@5.5.1", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-m1pAzaJgZ/gssEqlOhJkPJp8Xly7QyW6xcrkUa2KKcDeDSEMP7X8xipU3snUcfisTQx0w1AGae+9UtJSfVnXGw=="], + + "default-browser-id": ["default-browser-id@5.0.1", "", {}, "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q=="], + + "define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="], + + "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], + + "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="], + + "editions": ["editions@6.22.0", "", { "dependencies": { "version-range": "^4.15.0" } }, "sha512-UgGlf8IW75je7HZjNDpJdCv4cGJWIi6yumFdZ0R7A8/CIhQiWUjyGLCxdHpd8bmyD1gnkfUNK0oeOXqUS2cpfQ=="], + + "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], + + "entities": ["entities@8.1.0", "", {}, "sha512-kxL7msIffSuh9aaFAMD7rxAIuTRMAHMeBtgHW2yUdWw732ZNh4MehkF2gdjvtdmikkaIP9bFDDJOPlsvm7avrA=="], + + "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], + + "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], + + "es-object-atoms": ["es-object-atoms@1.1.2", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw=="], + + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "get-east-asian-width": ["get-east-asian-width@1.7.0", "", {}, "sha512-XjH1AECxf0giL2V1aU8vKyRR2ppRUb5c0EvT7zuJTokQ74bNo52zOtghqdWIqrhUD79fo3x0WfKZdOqxF6LG1Q=="], + + "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], + + "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], + + "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], + + "hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="], + + "hosted-git-info": ["hosted-git-info@4.1.0", "", { "dependencies": { "lru-cache": "^6.0.0" } }, "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA=="], + + "http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="], + + "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], + + "immediate": ["immediate@3.0.6", "", {}, "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="], + + "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], + + "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], + + "is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="], + + "is-interactive": ["is-interactive@2.0.0", "", {}, "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ=="], + + "is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="], + + "is-wsl": ["is-wsl@3.1.1", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw=="], + + "isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="], + + "istextorbinary": ["istextorbinary@9.5.0", "", { "dependencies": { "binaryextensions": "^6.11.0", "editions": "^6.21.0", "textextensions": "^6.11.0" } }, "sha512-5mbUj3SiZXCuRf9fT3ibzbSSEWiy63gFfksmGfdOzujPjW3k+z8WvIBxcJHBoQNlaZaiyB25deviif2+osLmLw=="], + + "jsonc-parser": ["jsonc-parser@3.3.1", "", {}, "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="], + + "jsonwebtoken": ["jsonwebtoken@9.0.3", "", { "dependencies": { "jws": "^4.0.1", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", "lodash.isnumber": "^3.0.3", "lodash.isplainobject": "^4.0.6", "lodash.isstring": "^4.0.1", "lodash.once": "^4.0.0", "ms": "^2.1.1", "semver": "^7.5.4" } }, "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g=="], + + "jszip": ["jszip@3.10.2", "", { "dependencies": { "lie": "~3.3.0", "pako": "~1.0.2", "readable-stream": "~2.3.6", "setimmediate": "^1.0.5" } }, "sha512-3l+rb15IOWtUhU0H5MFqES/T6Kh7abYwjosBey/vD6hDt8zoEffkSC5Ws5SGtgVw3gBx2NEbhTeSW1+kWkpyTQ=="], + + "jwa": ["jwa@2.0.1", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg=="], + + "jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="], + + "lie": ["lie@3.3.0", "", { "dependencies": { "immediate": "~3.0.5" } }, "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ=="], + + "lodash.includes": ["lodash.includes@4.3.0", "", {}, "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="], + + "lodash.isboolean": ["lodash.isboolean@3.0.3", "", {}, "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="], + + "lodash.isinteger": ["lodash.isinteger@4.0.4", "", {}, "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="], + + "lodash.isnumber": ["lodash.isnumber@3.0.3", "", {}, "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="], + + "lodash.isplainobject": ["lodash.isplainobject@4.0.6", "", {}, "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="], + + "lodash.isstring": ["lodash.isstring@4.0.1", "", {}, "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="], + + "lodash.once": ["lodash.once@4.1.1", "", {}, "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="], + + "log-symbols": ["log-symbols@6.0.0", "", { "dependencies": { "chalk": "^5.3.0", "is-unicode-supported": "^1.3.0" } }, "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw=="], + + "lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], + + "marked": ["marked@18.0.14", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-mBHK6FBHuBAlhgRe88w9F0O1AbwwXJUcQibUbC/QcdTbVGAD7aWza+xt3N6oT/jCZx3/OMeS+8rnuiHZcQ9s7A=="], + + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], + + "mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], + + "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="], + + "minimatch": ["minimatch@10.2.6", "", { "dependencies": { "brace-expansion": "^5.0.8" } }, "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "mute-stream": ["mute-stream@0.0.8", "", {}, "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="], + + "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], + + "onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="], + + "open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="], + + "ora": ["ora@8.2.0", "", { "dependencies": { "chalk": "^5.3.0", "cli-cursor": "^5.0.0", "cli-spinners": "^2.9.2", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.0.0", "log-symbols": "^6.0.0", "stdin-discarder": "^0.2.2", "string-width": "^7.2.0", "strip-ansi": "^7.1.0" } }, "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw=="], + + "pako": ["pako@1.0.11", "", {}, "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="], + + "parse5": ["parse5@8.0.1", "", { "dependencies": { "entities": "^8.0.0" } }, "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw=="], + + "pend": ["pend@1.2.0", "", {}, "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="], + + "picomatch": ["picomatch@4.0.7", "", {}, "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA=="], + + "process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="], + + "proper-lockfile": ["proper-lockfile@4.1.2", "", { "dependencies": { "graceful-fs": "^4.2.4", "retry": "^0.12.0", "signal-exit": "^3.0.2" } }, "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA=="], + + "qs": ["qs@6.16.0", "", { "dependencies": { "es-define-property": "^1.0.1", "side-channel": "^1.1.1" } }, "sha512-h6fhOIaRrID2CbEY2fqs+7t+UXZo+MLAnU5gRIq85uFtdiUPCdsApMlHhXogKVM4HM2DVbIjGNTTYH2OcmP1vA=="], + + "read": ["read@1.0.7", "", { "dependencies": { "mute-stream": "~0.0.4" } }, "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ=="], + + "readable-stream": ["readable-stream@2.3.8", "", { "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" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], + + "restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="], + + "retry": ["retry@0.12.0", "", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="], + + "rootform": ["rootform@workspace:vscode"], + + "run-applescript": ["run-applescript@7.1.0", "", {}, "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q=="], + + "safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], + + "sax": ["sax@1.6.1", "", {}, "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q=="], + + "semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="], + + "setimmediate": ["setimmediate@1.0.5", "", {}, "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="], + + "side-channel": ["side-channel@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4", "side-channel-list": "^1.0.1", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ=="], + + "side-channel-list": ["side-channel-list@1.0.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4" } }, "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w=="], + + "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], + + "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="], + + "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], + + "stdin-discarder": ["stdin-discarder@0.2.2", "", {}, "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ=="], + + "string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], + + "string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], + + "strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], + + "structured-source": ["structured-source@4.0.0", "", { "dependencies": { "boundary": "^2.0.0" } }, "sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA=="], + + "textextensions": ["textextensions@6.11.0", "", { "dependencies": { "editions": "^6.21.0" } }, "sha512-tXJwSr9355kFJI3lbCkPpUH5cP8/M0GGy2xLO34aZCjMXBaK3SoPnZwr/oWmo1FdCnELcs4npdCIOFtq9W3ruQ=="], + + "tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "tunnel": ["tunnel@0.0.6", "", {}, "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="], + + "typed-rest-client": ["typed-rest-client@1.8.11", "", { "dependencies": { "qs": "^6.9.1", "tunnel": "0.0.6", "underscore": "^1.12.1" } }, "sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA=="], + + "typescript": ["typescript@7.0.2", "", { "optionalDependencies": { "@typescript/typescript-aix-ppc64": "7.0.2", "@typescript/typescript-darwin-arm64": "7.0.2", "@typescript/typescript-darwin-x64": "7.0.2", "@typescript/typescript-freebsd-arm64": "7.0.2", "@typescript/typescript-freebsd-x64": "7.0.2", "@typescript/typescript-linux-arm": "7.0.2", "@typescript/typescript-linux-arm64": "7.0.2", "@typescript/typescript-linux-loong64": "7.0.2", "@typescript/typescript-linux-mips64el": "7.0.2", "@typescript/typescript-linux-ppc64": "7.0.2", "@typescript/typescript-linux-riscv64": "7.0.2", "@typescript/typescript-linux-s390x": "7.0.2", "@typescript/typescript-linux-x64": "7.0.2", "@typescript/typescript-netbsd-arm64": "7.0.2", "@typescript/typescript-netbsd-x64": "7.0.2", "@typescript/typescript-openbsd-arm64": "7.0.2", "@typescript/typescript-openbsd-x64": "7.0.2", "@typescript/typescript-sunos-x64": "7.0.2", "@typescript/typescript-win32-arm64": "7.0.2", "@typescript/typescript-win32-x64": "7.0.2" }, "bin": { "tsc": "bin/tsc" } }, "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA=="], + + "underscore": ["underscore@1.13.8", "", {}, "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ=="], + + "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + + "url-join": ["url-join@4.0.1", "", {}, "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA=="], + + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + + "version-range": ["version-range@4.15.0", "", {}, "sha512-Ck0EJbAGxHwprkzFO966t4/5QkRuzh+/I1RxhLgUKKwEn+Cd8NwM60mE3AqBZg5gYODoXW0EFsQvbZjRlvdqbg=="], + + "vscode-jsonrpc": ["vscode-jsonrpc@9.0.3", "", {}, "sha512-qETYf9PCl1lVfwR+oBmMfc4vP2nqLNA35ABxorw3j06+xlKRgDVxbLgKm4Y/xPL0YWdeDjLoI4ImICIT3nB0zQ=="], + + "vscode-languageclient": ["vscode-languageclient@10.1.2", "", { "dependencies": { "minimatch": "^10.2.6", "semver": "^7.8.1", "vscode-languageserver-protocol": "3.18.4", "vscode-languageserver-textdocument": "1.0.15" } }, "sha512-cOv5SMvtAhfVeo5m2r9L2rVHAD0J5CFOsmvH1WgNmPaI61VYjJNc3XUDLOKeFSDtWoAXIEoK6KetuBEL/3hErg=="], + + "vscode-languageserver-protocol": ["vscode-languageserver-protocol@3.18.4", "", { "dependencies": { "vscode-jsonrpc": "9.0.3", "vscode-languageserver-types": "3.18.4" } }, "sha512-CCXbyr99dafRJzJH/0Ryk7ly5T8XPmSR0//OuF2w4m+9JiOin7zcAT5iET8GRE7Z9taFBejb3GbM0a0mbjdbrg=="], + + "vscode-languageserver-textdocument": ["vscode-languageserver-textdocument@1.0.15", "", {}, "sha512-Gsfr9S8LU3S6885cS+NaleasJ0n3V5y/SOTqHCifQiXWFw3G9w9/YItDfwHrlCz+dSZWWZ8ilYVMcJe7Sz7Sxw=="], + + "vscode-languageserver-types": ["vscode-languageserver-types@3.18.4", "", {}, "sha512-nQsacoiijvl0fRf2q28uFDrAVwRhdCa3QveiF7/CX0r18mLR5FU/1WskSsCKOjmEbtteKUnY8x8Yzxop+k0zwg=="], + + "wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="], + + "xml2js": ["xml2js@0.5.0", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA=="], + + "xmlbuilder": ["xmlbuilder@11.0.1", "", {}, "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="], + + "yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "yauzl": ["yauzl@3.4.0", "", { "dependencies": { "pend": "~1.2.0" } }, "sha512-jIH9yLR9wqr0wOS0TpBvo/g/2UgZH5qePVbjgRliiF0BYvOZyaBknKsF+x9Iht0O6sqgnB93rCICdOZFecJuDw=="], + + "yazl": ["yazl@2.5.1", "", { "dependencies": { "buffer-crc32": "~0.2.3" } }, "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw=="], + + "log-symbols/is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="], + + "restore-cursor/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..426c9df --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "@rootform/editors-repository", + "private": true, + "version": "0.1.0", + "license": "Apache-2.0", + "packageManager": "bun@1.4.0", + "workspaces": [ + "vscode" + ], + "scripts": { + "verify": "bun scripts/verify.ts", + "check:format": "biome check .", + "format": "biome check --write .", + "build:vscode": "bun run --cwd vscode build", + "build:zed": "cargo +1.93.1 build --manifest-path zed/Cargo.toml --locked --release --target wasm32-wasip2" + }, + "devDependencies": { + "@biomejs/biome": "2.5.14", + "@types/bun": "1.4.0" + }, + "patchedDependencies": { + "vscode-languageclient@10.1.2": "patches/vscode-languageclient@10.1.2.patch" + } +} diff --git a/patches/vscode-languageclient@10.1.2.patch b/patches/vscode-languageclient@10.1.2.patch new file mode 100644 index 0000000..c21f6d7 --- /dev/null +++ b/patches/vscode-languageclient@10.1.2.patch @@ -0,0 +1,31 @@ +diff --git a/lib/common/client.js b/lib/common/client.js +index 05c900d02073cfc5b2d19ed400b5a1d434b74611..8103600b0d92d89bb1881ec89f7136bd94eb0e11 100644 +--- a/lib/common/client.js ++++ b/lib/common/client.js +@@ -1048,7 +1048,7 @@ class BaseLanguageClient { + this.error(`${this._name} client: couldn't create connection to server.`, error, 'force'); + reject(error); + } +- return this._onStart; ++ return promise; + } + createOnStartPromise() { + let resolve; +@@ -1168,7 +1168,7 @@ class BaseLanguageClient { + void this.initialize(connection); + } + else { +- void this.stop(); ++ void this.stop().catch(error => this.error('Stopping after initialization failure failed.', error, false)); + } + } + else if (error instanceof vscode_languageserver_protocol_1.ResponseError && error.data && error.data.retry) { +@@ -1217,7 +1217,7 @@ class BaseLanguageClient { + } + async shutdown(mode, timeout = 2000) { + // If the client is stopped or in its initial state return. +- if (this.$state === ClientState.Stopped || this.$state === ClientState.Initial) { ++ if (this.$state === ClientState.Stopped || this.$state === ClientState.Initial || this.$state === ClientState.StartFailed) { + return; + } + // If we are stopping the client and have a stop promise return it. diff --git a/scripts/verify.ts b/scripts/verify.ts new file mode 100644 index 0000000..3bde0d7 --- /dev/null +++ b/scripts/verify.ts @@ -0,0 +1,15 @@ +import { spawnSync } from "node:child_process"; + +if (Bun.version !== "1.4.0") throw new Error("Bun 1.4.0 is required"); +for (const command of [ + ["bun", "run", "check:format"], + ["bun", "run", "build:vscode"], + ["bun", "run", "--cwd", "vscode", "test:unit"], + ["cargo", "+1.93.1", "fmt", "--manifest-path", "zed/Cargo.toml", "--", "--check"], + ["cargo", "+1.93.1", "test", "--manifest-path", "zed/Cargo.toml", "--locked"], + ["bun", "run", "build:zed"], +]) { + const result = spawnSync(command[0]!, command.slice(1), { stdio: "inherit", shell: false }); + if (result.error) throw result.error; + if (result.status !== 0) process.exit(result.status ?? 1); +} diff --git a/vscode/.vscodeignore b/vscode/.vscodeignore new file mode 100644 index 0000000..6145f44 --- /dev/null +++ b/vscode/.vscodeignore @@ -0,0 +1,9 @@ +** +!package.json +!README.md +!LICENSE +!THIRD_PARTY_NOTICES.md +!licenses/** +!language-configuration.json +!syntaxes/** +!dist/** diff --git a/vscode/LICENSE b/vscode/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/vscode/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vscode/README.md b/vscode/README.md new file mode 100644 index 0000000..99c3879 --- /dev/null +++ b/vscode/README.md @@ -0,0 +1,39 @@ +# Rootform for VS Code + +Rootform adds the `rootform` language mode for `.rf.hcl`, HCL lexical coloring, +comments, bracket matching, automatic closing, indentation and folding. The +Rootform language server supplies diagnostics, completion, hover, definitions +and formatting. The extension contains no compiler, executable or provider. + +Install Rootform separately, then set **Rootform: Server Path** to an absolute +path to the local executable or leave it as `rootform` to resolve it through +`PATH`. In an untrusted workspace the extension does not launch a process. Trust +the workspace to start the configured executable. Run **Rootform: Restart +Language Server** after changing the executable outside VS Code. + +A process that does not complete LSP initialization within 10 seconds is +stopped with a setting remediation. A failed initial handshake is not retried +automatically; a process that dies after successful initialization uses the +language client's bounded restart policy. + +The package supports VS Code 1.133.0 and later. `.rf.json` files are also sent +to the same language server; VS Code keeps their JSON editor presentation. + +## Development + +The editor repository uses Bun workspaces. From the repository root, install +the lockfile once and run `bun run verify`. To qualify the real extension host, +provide both locally installed executables: + +```sh +VSCODE_EXECUTABLE_PATH="/Applications/Visual Studio Code.app/Contents/MacOS/Code" \ +ROOTFORM_BINARY="/absolute/path/to/rootform" \ +bun run --filter rootform test:integration +``` + +The integration runner uses a temporary multi-root fixture workspace and unique +VS Code user-data and extension directories. It does not download VS Code or +Rootform. The fixture language source is synthetic and contains no production +Engine implementation. + +Source is licensed under Apache-2.0. diff --git a/vscode/THIRD_PARTY_NOTICES.md b/vscode/THIRD_PARTY_NOTICES.md new file mode 100644 index 0000000..13d3d1d --- /dev/null +++ b/vscode/THIRD_PARTY_NOTICES.md @@ -0,0 +1,62 @@ +# Third-party notices for the VS Code extension + +The pinned `vscode-languageclient` 10.1.2 includes the repository's +[startup lifecycle patch](https://github.com/rootform-dev/editors/blob/dev/patches/vscode-languageclient%4010.1.2.patch). +It keeps the original startup promise after an early transport close and +handles cleanup of failed initialization. Upstream license text is unchanged. + +The Rootform VS Code extension's own source is licensed under Apache-2.0; see +[`LICENSE`](LICENSE). The bundled `dist/extension.js` also contains the npm +runtime packages listed below. Package versions and SHA-512 integrity values +are recorded in the repository's `bun.lock`. Upstream repositories and +subdirectories come from each package's metadata. Each linked license file is a +verbatim copy of that package's distributed license file. + +Build and packaging dependencies are excluded. The list covers the packages +present in the Bun bundle, including transitive runtime dependencies. + +- **balanced-match@4.0.4**, MIT. Upstream: + [juliangruber/balanced-match](https://github.com/juliangruber/balanced-match). + License copied from `LICENSE.md` to + [`licenses/balanced-match-4.0.4-LICENSE.md`](licenses/balanced-match-4.0.4-LICENSE.md). + Lock integrity: `sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==`. +- **brace-expansion@5.0.12**, MIT. Upstream: + [juliangruber/brace-expansion](https://github.com/juliangruber/brace-expansion). + License copied from `LICENSE` to + [`licenses/brace-expansion-5.0.12-LICENSE`](licenses/brace-expansion-5.0.12-LICENSE). + Lock integrity: `sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==`. +- **minimatch@10.2.6**, Blue Oak Model License 1.0.0 + (`BlueOak-1.0.0`). Upstream: + [isaacs/minimatch](https://github.com/isaacs/minimatch). License copied from + `LICENSE.md` to + [`licenses/minimatch-10.2.6-LICENSE.md`](licenses/minimatch-10.2.6-LICENSE.md). + Lock integrity: `sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==`. +- **semver@7.8.5**, ISC. Upstream: + [npm/node-semver](https://github.com/npm/node-semver). License copied from + `LICENSE` to [`licenses/semver-7.8.5-LICENSE`](licenses/semver-7.8.5-LICENSE). + Lock integrity: `sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==`. +- **vscode-jsonrpc@9.0.3**, MIT. Upstream: + [Microsoft/vscode-languageserver-node, `jsonrpc`](https://github.com/microsoft/vscode-languageserver-node/tree/main/jsonrpc). + License copied from `License.txt` to + [`licenses/vscode-jsonrpc-9.0.3-LICENSE.txt`](licenses/vscode-jsonrpc-9.0.3-LICENSE.txt). + Lock integrity: `sha512-qETYf9PCl1lVfwR+oBmMfc4vP2nqLNA35ABxorw3j06+xlKRgDVxbLgKm4Y/xPL0YWdeDjLoI4ImICIT3nB0zQ==`. +- **vscode-languageclient@10.1.2**, MIT. Upstream: + [Microsoft/vscode-languageserver-node, `client`](https://github.com/microsoft/vscode-languageserver-node/tree/main/client). + License copied from `License.txt` to + [`licenses/vscode-languageclient-10.1.2-LICENSE.txt`](licenses/vscode-languageclient-10.1.2-LICENSE.txt). + Lock integrity: `sha512-cOv5SMvtAhfVeo5m2r9L2rVHAD0J5CFOsmvH1WgNmPaI61VYjJNc3XUDLOKeFSDtWoAXIEoK6KetuBEL/3hErg==`. +- **vscode-languageserver-protocol@3.18.4**, MIT. Upstream: + [Microsoft/vscode-languageserver-node, `protocol`](https://github.com/microsoft/vscode-languageserver-node/tree/main/protocol). + License copied from `License.txt` to + [`licenses/vscode-languageserver-protocol-3.18.4-LICENSE.txt`](licenses/vscode-languageserver-protocol-3.18.4-LICENSE.txt). + Lock integrity: `sha512-CCXbyr99dafRJzJH/0Ryk7ly5T8XPmSR0//OuF2w4m+9JiOin7zcAT5iET8GRE7Z9taFBejb3GbM0a0mbjdbrg==`. +- **vscode-languageserver-textdocument@1.0.15**, MIT. Upstream: + [Microsoft/vscode-languageserver-node, `textDocument`](https://github.com/microsoft/vscode-languageserver-node/tree/main/textDocument). + License copied from `License.txt` to + [`licenses/vscode-languageserver-textdocument-1.0.15-LICENSE.txt`](licenses/vscode-languageserver-textdocument-1.0.15-LICENSE.txt). + Lock integrity: `sha512-Gsfr9S8LU3S6885cS+NaleasJ0n3V5y/SOTqHCifQiXWFw3G9w9/YItDfwHrlCz+dSZWWZ8ilYVMcJe7Sz7Sxw==`. +- **vscode-languageserver-types@3.18.4**, MIT. Upstream: + [Microsoft/vscode-languageserver-node, `types`](https://github.com/microsoft/vscode-languageserver-node/tree/main/types). + License copied from `License.txt` to + [`licenses/vscode-languageserver-types-3.18.4-LICENSE.txt`](licenses/vscode-languageserver-types-3.18.4-LICENSE.txt). + Lock integrity: `sha512-nQsacoiijvl0fRf2q28uFDrAVwRhdCa3QveiF7/CX0r18mLR5FU/1WskSsCKOjmEbtteKUnY8x8Yzxop+k0zwg==`. diff --git a/vscode/fixtures/integration/first/dialect.rf.hcl b/vscode/fixtures/integration/first/dialect.rf.hcl new file mode 100644 index 0000000..6d5c9b4 --- /dev/null +++ b/vscode/fixtures/integration/first/dialect.rf.hcl @@ -0,0 +1,8 @@ +dialect "demo" { + version = "0.1.0" + provider "example/testing" { version = "= 1.0.0" } +} + +concept "network" { + description = "Synthetic symbol for the VS Code integration fixture." +} diff --git a/vscode/fixtures/integration/first/rule.rf.hcl b/vscode/fixtures/integration/first/rule.rf.hcl new file mode 100644 index 0000000..5504333 --- /dev/null +++ b/vscode/fixtures/integration/first/rule.rf.hcl @@ -0,0 +1,6 @@ +rule "network"{ +match{ +type="example_network" +} +as=concept.network +} diff --git a/vscode/fixtures/integration/json/dialect.rf.json b/vscode/fixtures/integration/json/dialect.rf.json new file mode 100644 index 0000000..25f880c --- /dev/null +++ b/vscode/fixtures/integration/json/dialect.rf.json @@ -0,0 +1,12 @@ +{ + "dialect": { + "json-owner": { + "version": "0.1.0" + } + }, + "concept": { + "json-service": { + "description": "Synthetic JSON source root." + } + } +} diff --git a/vscode/fixtures/integration/policies/checks.rf.hcl b/vscode/fixtures/integration/policies/checks.rf.hcl new file mode 100644 index 0000000..0ca4671 --- /dev/null +++ b/vscode/fixtures/integration/policies/checks.rf.hcl @@ -0,0 +1,7 @@ +policy_pack "checks" { version = "0.1.0" } + +policy "network" { + target { concept = demo.concept.network } + assert = length(contexts(rf.context.network)) > 0 + message = "Network context required." +} diff --git a/vscode/fixtures/integration/second/dialect.rf.hcl b/vscode/fixtures/integration/second/dialect.rf.hcl new file mode 100644 index 0000000..36582dc --- /dev/null +++ b/vscode/fixtures/integration/second/dialect.rf.hcl @@ -0,0 +1,7 @@ +dialect "peer" { + version = "0.1.0" +} + +concept "service" { + description = "Second synthetic workspace root." +} diff --git a/vscode/fixtures/lexical/sample.rf.hcl b/vscode/fixtures/lexical/sample.rf.hcl new file mode 100644 index 0000000..381c159 --- /dev/null +++ b/vscode/fixtures/lexical/sample.rf.hcl @@ -0,0 +1,15 @@ +# Synthetic lexical fixture. Hash, slash, and block comments are HCL syntax. +// Rootform block names are highlighted lexically, without semantic analysis. +/* A block comment can span lines. */ +dialect "sample" { + version = "0.1.0" +} + +concept "network" { + description = "A synthetic ${var.name} value" + enabled = true + count = 2 + note = <<-EOT + Example heredoc text. + EOT +} diff --git a/vscode/language-configuration.json b/vscode/language-configuration.json new file mode 100644 index 0000000..b670f8a --- /dev/null +++ b/vscode/language-configuration.json @@ -0,0 +1,25 @@ +{ + "comments": { + "lineComment": "#", + "blockComment": ["/*", "*/"] + }, + "brackets": [["{", "}"], ["[", "]"], ["(", ")"]], + "autoClosingPairs": [ + { "open": "{", "close": "}" }, + { "open": "[", "close": "]" }, + { "open": "(", "close": ")" }, + { "open": "\"", "close": "\"", "notIn": ["string", "comment"] }, + { "open": "/*", "close": "*/", "notIn": ["string"] } + ], + "surroundingPairs": [["{", "}"], ["[", "]"], ["(", ")"], ["\"", "\""]], + "indentationRules": { + "increaseIndentPattern": "^.*(?:\\{|\\[|\\()\\s*$", + "decreaseIndentPattern": "^\\s*[}\\])]" + }, + "folding": { + "markers": { + "start": "^\\s*(#|//)\\s*region\\b", + "end": "^\\s*(#|//)\\s*endregion\\b" + } + } +} diff --git a/vscode/licenses/balanced-match-4.0.4-LICENSE.md b/vscode/licenses/balanced-match-4.0.4-LICENSE.md new file mode 100644 index 0000000..61ece8c --- /dev/null +++ b/vscode/licenses/balanced-match-4.0.4-LICENSE.md @@ -0,0 +1,23 @@ +(MIT) + +Original code Copyright Julian Gruber + +Port to TypeScript Copyright Isaac Z. Schlueter + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vscode/licenses/brace-expansion-5.0.12-LICENSE b/vscode/licenses/brace-expansion-5.0.12-LICENSE new file mode 100644 index 0000000..46e7b75 --- /dev/null +++ b/vscode/licenses/brace-expansion-5.0.12-LICENSE @@ -0,0 +1,23 @@ +MIT License + +Copyright Julian Gruber + +TypeScript port Copyright Isaac Z. Schlueter + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vscode/licenses/minimatch-10.2.6-LICENSE.md b/vscode/licenses/minimatch-10.2.6-LICENSE.md new file mode 100644 index 0000000..8cb5cc6 --- /dev/null +++ b/vscode/licenses/minimatch-10.2.6-LICENSE.md @@ -0,0 +1,55 @@ +# Blue Oak Model License + +Version 1.0.0 + +## Purpose + +This license gives everyone as much permission to work with +this software as possible, while protecting contributors +from liability. + +## Acceptance + +In order to receive this license, you must agree to its +rules. The rules of this license are both obligations +under that agreement and conditions to your license. +You must not do anything with this software that triggers +a rule that you cannot or will not follow. + +## Copyright + +Each contributor licenses you to do everything with this +software that would otherwise infringe that contributor's +copyright in it. + +## Notices + +You must ensure that everyone who gets a copy of +any part of this software from you, with or without +changes, also gets the text of this license or a link to +. + +## Excuse + +If anyone notifies you in writing that you have not +complied with [Notices](#notices), you can keep your +license by taking all practical steps to comply within 30 +days after the notice. If you do not do so, your license +ends immediately. + +## Patent + +Each contributor licenses you to do everything with this +software that would otherwise infringe any patent claims +they can license or become able to license. + +## Reliability + +No contributor can revoke this license. + +## No Liability + +**_As far as the law allows, this software comes as is, +without any warranty or condition, and no contributor +will be liable to anyone for any damages related to this +software or this license, under any kind of legal claim._** diff --git a/vscode/licenses/semver-7.8.5-LICENSE b/vscode/licenses/semver-7.8.5-LICENSE new file mode 100644 index 0000000..19129e3 --- /dev/null +++ b/vscode/licenses/semver-7.8.5-LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/vscode/licenses/vscode-jsonrpc-9.0.3-LICENSE.txt b/vscode/licenses/vscode-jsonrpc-9.0.3-LICENSE.txt new file mode 100644 index 0000000..a07e3ae --- /dev/null +++ b/vscode/licenses/vscode-jsonrpc-9.0.3-LICENSE.txt @@ -0,0 +1,11 @@ +Copyright (c) Microsoft Corporation + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vscode/licenses/vscode-languageclient-10.1.2-LICENSE.txt b/vscode/licenses/vscode-languageclient-10.1.2-LICENSE.txt new file mode 100644 index 0000000..a07e3ae --- /dev/null +++ b/vscode/licenses/vscode-languageclient-10.1.2-LICENSE.txt @@ -0,0 +1,11 @@ +Copyright (c) Microsoft Corporation + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vscode/licenses/vscode-languageserver-protocol-3.18.4-LICENSE.txt b/vscode/licenses/vscode-languageserver-protocol-3.18.4-LICENSE.txt new file mode 100644 index 0000000..a07e3ae --- /dev/null +++ b/vscode/licenses/vscode-languageserver-protocol-3.18.4-LICENSE.txt @@ -0,0 +1,11 @@ +Copyright (c) Microsoft Corporation + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vscode/licenses/vscode-languageserver-textdocument-1.0.15-LICENSE.txt b/vscode/licenses/vscode-languageserver-textdocument-1.0.15-LICENSE.txt new file mode 100644 index 0000000..a07e3ae --- /dev/null +++ b/vscode/licenses/vscode-languageserver-textdocument-1.0.15-LICENSE.txt @@ -0,0 +1,11 @@ +Copyright (c) Microsoft Corporation + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vscode/licenses/vscode-languageserver-types-3.18.4-LICENSE.txt b/vscode/licenses/vscode-languageserver-types-3.18.4-LICENSE.txt new file mode 100644 index 0000000..a07e3ae --- /dev/null +++ b/vscode/licenses/vscode-languageserver-types-3.18.4-LICENSE.txt @@ -0,0 +1,11 @@ +Copyright (c) Microsoft Corporation + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vscode/package.json b/vscode/package.json new file mode 100644 index 0000000..8ac6e8d --- /dev/null +++ b/vscode/package.json @@ -0,0 +1,96 @@ +{ + "name": "rootform", + "displayName": "Rootform", + "description": "Thin VS Code language client for Rootform source files.", + "publisher": "rootform-dev", + "version": "0.1.0", + "license": "Apache-2.0", + "engines": { + "vscode": "^1.133.0" + }, + "categories": [ + "Programming Languages" + ], + "main": "./dist/extension.js", + "activationEvents": [ + "onLanguage:rootform", + "workspaceContains:**/*.rf.json" + ], + "scripts": { + "build": "bun run compile && bun build src/extension.ts --outdir dist --target node --format cjs --external vscode", + "compile": "tsc --project tsconfig.json", + "test:unit": "bun run compile && node --test test/serverController.test.cjs", + "test:integration": "bun run build && node test/run-integration.cjs", + "verify": "bun run test:unit", + "vscode:prepublish": "bun run build", + "package": "vsce package --no-dependencies" + }, + "dependencies": { + "vscode-languageclient": "10.1.2" + }, + "devDependencies": { + "@types/node": "22.20.4", + "@types/vscode": "1.91.0", + "@vscode/test-electron": "3.1.0", + "@vscode/vsce": "4.0.0", + "typescript": "7.0.2" + }, + "contributes": { + "configurationDefaults": { + "[rootform]": { + "editor.wordBasedSuggestions": "off" + } + }, + "languages": [ + { + "id": "rootform", + "aliases": [ + "Rootform", + "rootform" + ], + "extensions": [ + ".rf.hcl" + ], + "configuration": "./language-configuration.json" + } + ], + "grammars": [ + { + "language": "rootform", + "scopeName": "source.rootform", + "path": "./syntaxes/rootform.tmLanguage.json" + } + ], + "commands": [ + { + "command": "rootform.restartLanguageServer", + "title": "Rootform: Restart Language Server" + } + ], + "configuration": { + "title": "Rootform", + "properties": { + "rootform.server.path": { + "type": "string", + "default": "rootform", + "scope": "machine-overridable", + "description": "Absolute path or command name resolved through PATH for a local Rootform executable. The executable is started with the lsp command." + } + } + } + }, + "capabilities": { + "untrustedWorkspaces": { + "supported": "limited", + "description": "Rootform starts the configured local executable only in trusted workspaces.", + "restrictedConfigurations": [ + "rootform.server.path" + ] + } + }, + "repository": { + "type": "git", + "url": "https://github.com/rootform-dev/editors.git", + "directory": "vscode" + } +} diff --git a/vscode/src/extension.ts b/vscode/src/extension.ts new file mode 100644 index 0000000..4a6449a --- /dev/null +++ b/vscode/src/extension.ts @@ -0,0 +1,148 @@ +import * as vscode from "vscode"; +import type { + ErrorHandler, + LanguageClientOptions, + ServerOptions, +} from "vscode-languageclient/node"; +import { CloseAction, LanguageClient } from "vscode-languageclient/node"; +import { + INITIALIZE_TIMEOUT_MS, + MAX_RESTART_COUNT, + ServerController, + startupFailureMessage, +} from "./serverController"; + +let controller: ServerController | undefined; + +class RootformLanguageClient extends LanguageClient { + private initializing = false; + private initializedSuccessfully = false; + + override async start(): Promise { + this.initializing = true; + let timedOut = false; + const deadline = setTimeout(() => { + timedOut = true; + this.serverProcess?.kill("SIGKILL"); + }, INITIALIZE_TIMEOUT_MS); + try { + await super.start(); + this.initializedSuccessfully = true; + } catch (error) { + if (timedOut) { + throw Object.assign(new Error("Rootform LSP initialization timed out."), { + code: "ROOTFORM_LSP_INITIALIZE_TIMEOUT", + }); + } + throw error; + } finally { + clearTimeout(deadline); + this.initializing = false; + } + } + + override error( + message: string, + data?: unknown, + showNotification: boolean | "force" = true, + ): void { + // The controller presents startup failures once, with the setting remediation. + // Keep SDK logging and notifications for failures after startup. + super.error(message, data, this.initializing ? false : showNotification); + } + + override createDefaultErrorHandler(maxRestartCount?: number): ErrorHandler { + const handler = super.createDefaultErrorHandler(maxRestartCount); + return { + error: (error, message, count) => handler.error(error, message, count), + closed: () => + this.initializedSuccessfully + ? handler.closed() + : { action: CloseAction.DoNotRestart, handled: true }, + }; + } +} + +export function activate(context: vscode.ExtensionContext): void { + const output = vscode.window.createOutputChannel("Rootform", { log: true }); + context.subscriptions.push(output); + + const watchers = [ + "**/*.rf.hcl", + "**/*.rf.json", + "**/rootform.lock", + "**/.terraform.lock.hcl", + ].map((pattern) => vscode.workspace.createFileSystemWatcher(pattern)); + context.subscriptions.push(...watchers); + + const host = { + isTrusted: () => vscode.workspace.isTrusted, + executablePath: () => + vscode.workspace.getConfiguration("rootform").get("server.path", "rootform"), + createClient: (executablePath: string) => { + const serverOptions: ServerOptions = { + command: executablePath, + args: ["lsp"], + options: { + cwd: context.extensionPath, + shell: false, + }, + }; + const clientOptions: LanguageClientOptions = { + documentSelector: [ + { scheme: "file", language: "rootform" }, + { scheme: "file", pattern: "**/*.rf.json" }, + ], + synchronize: { fileEvents: watchers }, + outputChannel: output, + connectionOptions: { maxRestartCount: MAX_RESTART_COUNT }, + initializationFailedHandler: () => false, + }; + + // Leave transport unset. Rootform accepts `lsp` without a `--stdio` flag. + return new RootformLanguageClient("rootform", "Rootform", serverOptions, clientOptions); + }, + reportStartupFailure: (executablePath: string, error: unknown) => { + const message = startupFailureMessage(executablePath, error); + output.error(message); + output.error(error instanceof Error ? (error.stack ?? error.message) : String(error)); + void vscode.window.showErrorMessage(message, "Open Setting").then((choice) => { + if (choice === "Open Setting") { + void vscode.commands.executeCommand( + "workbench.action.openSettings", + "rootform.server.path", + ); + } + }); + }, + reportStopFailure: (error: unknown) => { + output.error("Rootform language server shutdown failed."); + output.error(error instanceof Error ? (error.stack ?? error.message) : String(error)); + }, + }; + + controller = new ServerController(host); + const activeController = controller; + + context.subscriptions.push( + vscode.workspace.onDidGrantWorkspaceTrust(() => { + void activeController.start(); + }), + vscode.workspace.onDidChangeConfiguration((event) => { + if (event.affectsConfiguration("rootform.server.path")) { + void activeController.restart(); + } + }), + vscode.commands.registerCommand("rootform.restartLanguageServer", () => + activeController.restart(), + ), + ); + + if (vscode.workspace.isTrusted) void activeController.start(); +} + +export async function deactivate(): Promise { + const activeController = controller; + controller = undefined; + if (activeController) await activeController.dispose(); +} diff --git a/vscode/src/serverController.ts b/vscode/src/serverController.ts new file mode 100644 index 0000000..22a70c6 --- /dev/null +++ b/vscode/src/serverController.ts @@ -0,0 +1,129 @@ +export const MAX_RESTART_COUNT = 4; +export const INITIALIZE_TIMEOUT_MS = 10_000; + +export interface LanguageServerClient { + start(): Promise; + dispose(): Promise; +} + +export interface ServerControllerHost { + isTrusted(): boolean; + executablePath(): string; + createClient(executablePath: string): LanguageServerClient; + reportStartupFailure(executablePath: string, error: unknown): void; + reportStopFailure(error: unknown): void; +} + +export class ServerController { + private currentClient: LanguageServerClient | undefined; + private queue: Promise = Promise.resolve(); + private disposed = false; + + constructor(private readonly host: ServerControllerHost) {} + + start(): Promise { + return this.enqueue(async () => { + if (!this.host.isTrusted()) { + await this.stopCurrentClient(); + return; + } + await this.startIfNeeded(); + }); + } + + restart(): Promise { + return this.enqueue(async () => { + if (this.disposed) return; + await this.stopCurrentClient(); + if (this.host.isTrusted()) await this.startIfNeeded(); + }); + } + + dispose(): Promise { + return this.enqueue(async () => { + this.disposed = true; + await this.stopCurrentClient(); + }); + } + + private enqueue(operation: () => Promise): Promise { + const result = this.queue.then(operation, operation); + this.queue = result.catch(() => undefined); + return result; + } + + private async startIfNeeded(): Promise { + if (this.disposed || this.currentClient) return; + + const executablePath = this.host.executablePath().trim(); + if (!executablePath) { + this.host.reportStartupFailure(executablePath, new Error("The executable path is empty.")); + return; + } + + let client: LanguageServerClient; + try { + client = this.host.createClient(executablePath); + } catch (error) { + this.host.reportStartupFailure(executablePath, error); + return; + } + + this.currentClient = client; + try { + await client.start(); + } catch (error) { + if (this.currentClient === client) this.currentClient = undefined; + try { + await client.dispose(); + } catch (stopError) { + this.host.reportStopFailure(stopError); + } + this.host.reportStartupFailure(executablePath, error); + } + } + + private async stopCurrentClient(): Promise { + const client = this.currentClient; + this.currentClient = undefined; + if (!client) return; + + try { + await client.dispose(); + } catch (error) { + this.host.reportStopFailure(error); + } + } +} + +export function startupFailureMessage(executablePath: string, error: unknown): string { + if (!executablePath) { + return 'Rootform executable path is empty. Set "rootform.server.path" to a local Rootform executable or the command rootform.'; + } + + const code = errorCode(error); + if (code === "ROOTFORM_LSP_INITIALIZE_TIMEOUT") { + return `Rootform language server did not initialize within ${INITIALIZE_TIMEOUT_MS / 1000} seconds from "${executablePath}". Confirm it supports "rootform lsp" or change "rootform.server.path".`; + } + if (code === "ENOENT") { + return `Rootform executable "${executablePath}" was not found. Install Rootform or set "rootform.server.path" to a local executable.`; + } + if (code === "EACCES" || code === "EPERM") { + return `Rootform executable "${executablePath}" could not be run. Check its permissions or change "rootform.server.path".`; + } + + return `Rootform language server could not initialize from "${executablePath}". Confirm it supports "rootform lsp", then inspect the Rootform output channel.`; +} + +function errorCode(error: unknown): string | undefined { + // vscode-languageclient 10.1.2 serializes failed spawn errors in this form. + // Do not classify arbitrary initialization text as an operating-system error. + if (typeof error === "string") { + return /^Launching server using command .+ failed\. Error: spawn .+ (ENOENT|EACCES|EPERM)$/s.exec( + error, + )?.[1]; + } + if (typeof error !== "object" || error === null || !("code" in error)) return undefined; + const code = error.code; + return typeof code === "string" ? code : undefined; +} diff --git a/vscode/syntaxes/rootform.tmLanguage.json b/vscode/syntaxes/rootform.tmLanguage.json new file mode 100644 index 0000000..4ea3b90 --- /dev/null +++ b/vscode/syntaxes/rootform.tmLanguage.json @@ -0,0 +1,112 @@ +{ + "name": "Rootform", + "scopeName": "source.rootform", + "fileTypes": ["rf.hcl"], + "patterns": [ + { "include": "#comments" }, + { "include": "#heredoc" }, + { "include": "#strings" }, + { "include": "#blocks" }, + { "include": "#attributes" }, + { "include": "#constants" }, + { "include": "#numbers" }, + { "include": "#operators" }, + { "include": "#punctuation" } + ], + "repository": { + "comments": { + "patterns": [ + { + "name": "comment.line.number-sign.hcl", + "match": "#.*$" + }, + { + "name": "comment.line.double-slash.hcl", + "match": "//.*$" + }, + { + "name": "comment.block.hcl", + "begin": "/\\*", + "end": "\\*/", + "beginCaptures": { "0": { "name": "punctuation.definition.comment.hcl" } }, + "endCaptures": { "0": { "name": "punctuation.definition.comment.hcl" } } + } + ] + }, + "heredoc": { + "name": "string.unquoted.heredoc.hcl", + "begin": "<<-?([A-Za-z_][A-Za-z0-9_]*)", + "beginCaptures": { + "0": { "name": "punctuation.definition.string.begin.hcl" }, + "1": { "name": "entity.name.tag.heredoc.hcl" } + }, + "end": "^\\s*\\1\\s*$", + "endCaptures": { "0": { "name": "punctuation.definition.string.end.hcl" } } + }, + "strings": { + "name": "string.quoted.double.hcl", + "begin": "\"", + "end": "\"", + "beginCaptures": { "0": { "name": "punctuation.definition.string.begin.hcl" } }, + "endCaptures": { "0": { "name": "punctuation.definition.string.end.hcl" } }, + "patterns": [ + { + "name": "constant.character.escape.hcl", + "match": "\\\\(?:[\\\\\"nrt]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8])" + }, + { + "name": "meta.interpolation.hcl", + "begin": "\\$\\{", + "end": "\\}", + "beginCaptures": { "0": { "name": "punctuation.section.interpolation.begin.hcl" } }, + "endCaptures": { "0": { "name": "punctuation.section.interpolation.end.hcl" } }, + "patterns": [ + { "include": "#constants" }, + { "include": "#numbers" }, + { "include": "#operators" }, + { "include": "#punctuation" } + ] + } + ] + }, + "blocks": { + "name": "keyword.control.block.rootform", + "match": "\\b(?:dialect|concept|context|relation|rule|policy_pack|policy|provider|match|identity|endpoint|contribution|composition|member|target)\\b(?=\\s*(?:\"(?:\\\\.|[^\"])*\"|[A-Za-z_][A-Za-z0-9_-]*)?\\s*\\{)" + }, + "attributes": { + "patterns": [ + { + "name": "variable.other.property.hcl", + "match": "\\b[A-Za-z_][A-Za-z0-9_-]*(?=\\s*=)" + }, + { + "name": "entity.name.function.hcl", + "match": "\\b[A-Za-z_][A-Za-z0-9_-]*(?=\\s*\\()" + } + ] + }, + "constants": { + "patterns": [ + { "name": "constant.language.boolean.hcl", "match": "\\b(?:true|false)\\b" }, + { "name": "constant.language.null.hcl", "match": "\\bnull\\b" }, + { "name": "variable.other.readwrite.hcl", "match": "\\b[A-Za-z_][A-Za-z0-9_-]*\\b" } + ] + }, + "numbers": { + "name": "constant.numeric.hcl", + "match": "(?=|&&|\\|\\||=>|[=+*/%<>!-])" + }, + "punctuation": { + "patterns": [ + { "name": "punctuation.section.block.begin.hcl", "match": "[{}]" }, + { "name": "punctuation.section.sequence.hcl", "match": "[\\[\\]()]" }, + { "name": "punctuation.separator.comma.hcl", "match": "," }, + { "name": "punctuation.accessor.hcl", "match": "\\." } + ] + } + } +} diff --git a/vscode/test/extensionHost.cjs b/vscode/test/extensionHost.cjs new file mode 100644 index 0000000..6c3ac2c --- /dev/null +++ b/vscode/test/extensionHost.cjs @@ -0,0 +1,876 @@ +const assert = require("node:assert/strict"); +const cp = require("node:child_process"); +const fs = require("node:fs/promises"); +const path = require("node:path"); +const vscode = require("vscode"); + +function delay(milliseconds) { + return new Promise((resolve) => setTimeout(resolve, milliseconds)); +} + +function completionLabel(item) { + return typeof item.label === "string" ? item.label : (item.label?.label ?? ""); +} + +const MATCH_KINDS = [ + "settings", + "provider", + "resource", + "data", + "ephemeral", + "action", + "module", + "variable", + "local", + "output", + "moved", + "removed", + "import", + "check", + "language", +]; + +const CLOSED_ENUM_COMPLETIONS = new Set([ + ...MATCH_KINDS, + "global", + "absent", + "indeterminate", + "allow", + "deny", + "none", + "record", + "report", +]); + +const SCHEMA_COMPLETIONS = new Set([ + "as", + "match", + "identity", + "endpoint", + "context", + "contribution", + "relation", + "composition", + "member", + "kind", + "type", + "where", + "by", + "strategy", + "scope", + "on_null", + "external", + "disclose", + ...CLOSED_ENUM_COMPLETIONS, +]); + +const COMPLETION_CURSOR = "<|>"; + +function completionItems(result) { + return Array.isArray(result) ? result : (result?.items ?? []); +} + +function schemaCompletionLabels(items) { + return [ + ...new Set(items.map(completionLabel).filter((label) => SCHEMA_COMPLETIONS.has(label))), + ].sort(); +} + +function assertSchemaCompletions(items, expected, description) { + assert.deepEqual(schemaCompletionLabels(items), [...expected].sort(), description); + for (const item of items) { + const label = completionLabel(item); + if (CLOSED_ENUM_COMPLETIONS.has(label)) { + assert.equal( + item.detail, + undefined, + `Closed enum completion ${label} should have no detail.`, + ); + } + } +} + +function assertNoClosedEnumCompletions(items, description) { + const suggestions = [...new Set(items.map(completionLabel))].filter((label) => + CLOSED_ENUM_COMPLETIONS.has(label), + ); + assert.deepEqual(suggestions, [], description); +} + +async function completionsAt(document, markedSource) { + const cursorOffset = markedSource.indexOf(COMPLETION_CURSOR); + assert.notEqual(cursorOffset, -1, "Completion source must contain its cursor marker."); + assert.equal( + markedSource.indexOf(COMPLETION_CURSOR, cursorOffset + COMPLETION_CURSOR.length), + -1, + "Completion source must contain exactly one cursor marker.", + ); + const source = + markedSource.slice(0, cursorOffset) + + markedSource.slice(cursorOffset + COMPLETION_CURSOR.length); + await replaceDocument(document, source); + const position = document.positionAt(cursorOffset); + const result = await vscode.commands.executeCommand( + "vscode.executeCompletionItemProvider", + document.uri, + position, + ); + return { items: completionItems(result), position, source }; +} + +function completionSnippetText(item) { + if (((item.insertTextRules ?? 0) & 4) === 0) return undefined; + const text = item.textEdit?.newText ?? item.insertText; + if (typeof text === "string") return text; + return typeof text?.value === "string" ? text.value : undefined; +} + +async function until(description, predicate, timeoutMs = 15000) { + const deadline = Date.now() + timeoutMs; + while (Date.now() < deadline) { + const result = await predicate(); + if (result) return result; + await delay(100); + } + const diagnostics = vscode.languages.getDiagnostics().map(([uri, items]) => ({ + file: uri.fsPath, + diagnostics: items.map(({ code, message, range }) => ({ code, message, range })), + })); + throw new Error(`Timed out waiting for ${description}.\n${JSON.stringify(diagnostics, null, 2)}`); +} + +async function replaceDocument(document, content) { + const edit = new vscode.WorkspaceEdit(); + const entireDocument = new vscode.Range( + document.positionAt(0), + document.positionAt(document.getText().length), + ); + edit.replace(document.uri, entireDocument, content); + assert.equal(await vscode.workspace.applyEdit(edit), true); +} + +async function openFile(filename) { + const document = await vscode.workspace.openTextDocument(vscode.Uri.file(filename)); + await vscode.window.showTextDocument(document, { preview: false }); + return document; +} + +async function exerciseCompletionMatrix(firstRoot) { + const scratchPath = path.join(firstRoot, `completion-${process.pid}-${Date.now()}.rf.hcl`); + const previousEditor = vscode.window.activeTextEditor; + const previousSelection = previousEditor?.selection; + const previousViewColumn = previousEditor?.viewColumn; + let document; + + await fs.writeFile(scratchPath, "", { flag: "wx" }); + try { + document = await openFile(scratchPath); + assert.equal( + vscode.workspace.getConfiguration("editor", document).get("wordBasedSuggestions"), + "off", + "Rootform should not mix document word guesses with semantic completions.", + ); + const cases = [ + { + name: "empty rule body", + source: `rule "completion" {\n ${COMPLETION_CURSOR}\n}`, + expected: [ + "as", + "match", + "identity", + "endpoint", + "context", + "contribution", + "relation", + "composition", + ], + }, + { + name: "empty rule.match body", + source: `rule "completion" {\n match {\n ${COMPLETION_CURSOR}\n }\n}`, + expected: ["kind", "type", "where"], + }, + { + name: "nested relation.match body", + source: `rule "completion" {\n relation "related" {\n match {\n ${COMPLETION_CURSOR}\n }\n }\n}`, + expected: ["by", "strategy"], + }, + { + name: "composition.member.match body", + source: `rule "completion" {\n composition {\n member "part" {\n match {\n ${COMPLETION_CURSOR}\n }\n }\n }\n}`, + expected: ["kind", "type", "where"], + }, + { + name: "identity.scope values", + source: `rule "completion" {\n identity {\n scope = "${COMPLETION_CURSOR}"\n }\n}`, + expected: ["provider", "global"], + }, + { + name: "relation.on_null values", + source: `rule "completion" {\n relation "related" {\n on_null = "${COMPLETION_CURSOR}"\n }\n}`, + expected: ["absent", "indeterminate"], + }, + { + name: "context.external values", + source: `rule "completion" {\n context {\n external = "${COMPLETION_CURSOR}"\n }\n}`, + expected: ["allow", "deny"], + }, + { + name: "context.disclose values", + source: `rule "completion" {\n context {\n disclose = "${COMPLETION_CURSOR}"\n }\n}`, + expected: ["none", "record", "report"], + }, + { + name: "rule.match.kind values", + source: `rule "completion" {\n match {\n kind = "${COMPLETION_CURSOR}"\n }\n}`, + expected: MATCH_KINDS, + }, + ]; + + let emptyRule; + for (const testCase of cases) { + const result = await completionsAt(document, testCase.source); + assertSchemaCompletions( + result.items, + testCase.expected, + `Rootform completion in ${testCase.name}.`, + ); + if (testCase.name === "empty rule body") emptyRule = result; + } + + const matchItem = emptyRule.items.find((item) => completionLabel(item) === "match"); + const matchSnippet = matchItem && completionSnippetText(matchItem); + if (matchSnippet !== undefined) { + await replaceDocument(document, emptyRule.source); + const editor = await vscode.window.showTextDocument(document, { preview: false }); + editor.selection = new vscode.Selection(emptyRule.position, emptyRule.position); + await vscode.commands.executeCommand("editor.action.insertSnippet", { + snippet: matchSnippet, + }); + const insertedText = document.getText(); + const cursorOffset = document.offsetAt(editor.selection.active); + const matchStart = insertedText.lastIndexOf("match", cursorOffset); + const openingBrace = insertedText.indexOf("{", matchStart); + const closingBrace = insertedText.indexOf("}", cursorOffset); + assert.ok(matchStart >= 0 && openingBrace > matchStart); + assert.ok( + cursorOffset > openingBrace && closingBrace > cursorOffset, + "Body snippet should leave the cursor inside the inserted match block.", + ); + assert.equal( + /\$(?:\d+|\{\d+[^}]*\})/.test(insertedText), + false, + "VS Code should resolve snippet placeholders.", + ); + await replaceDocument(document, emptyRule.source); + } + + const emptyReference = await completionsAt( + document, + `rule "empty-reference" {\n as = ${COMPLETION_CURSOR}\n}`, + ); + assertNoClosedEnumCompletions( + emptyReference.items, + "An empty Concept reference should not offer closed enum values.", + ); + assert.ok( + emptyReference.items.some((item) => { + const label = completionLabel(item); + return label === "network" || label.endsWith(".concept.network"); + }), + "An empty as value should offer the local Concept reference.", + ); + assert.equal( + emptyReference.items.some((item) => { + const label = completionLabel(item); + return ( + label === "service" || + label.endsWith(".service") || + label === "json-service" || + label.endsWith(".json-service") + ); + }), + false, + "An empty as value must stay within the first workspace root.", + ); + + const occupiedRule = await completionsAt( + document, + `rule "occupied-singletons" {\n match { type = "example_network" }\n as = concept.network\n identity { scope = "provider" }\n endpoint { attributes = [] }\n composition {\n member "part" {\n via = source.part\n match { type = "example_network" }\n }\n }\n ${COMPLETION_CURSOR}\n}`, + ); + assertSchemaCompletions( + occupiedRule.items, + ["context", "contribution", "relation"], + "Occupied singleton rule fields and blocks should be omitted.", + ); + + const occupiedMatch = await completionsAt( + document, + `rule "occupied-match" {\n match {\n kind = "resource"\n type = "example_network"\n ${COMPLETION_CURSOR}\n }\n}`, + ); + assertSchemaCompletions( + occupiedMatch.items, + ["where"], + "Occupied match attributes should be omitted.", + ); + + const occupiedRelationMatch = await completionsAt( + document, + `rule "occupied-relation-match" {\n relation "related" {\n match {\n by = target.path\n ${COMPLETION_CURSOR}\n }\n }\n}`, + ); + assertSchemaCompletions( + occupiedRelationMatch.items, + ["strategy"], + "An occupied relation.match.by attribute should be omitted.", + ); + + for (const [name, source] of [ + ["match.type", `rule "open-type" {\n match {\n type = "${COMPLETION_CURSOR}"\n }\n}`], + ["description", `concept "open-description" {\n description = "${COMPLETION_CURSOR}"\n}`], + ]) { + const result = await completionsAt(document, source); + assertNoClosedEnumCompletions( + result.items, + `An arbitrary ${name} string should not offer closed enum values.`, + ); + } + } finally { + try { + if (document) { + await replaceDocument(document, ""); + await document.save(); + await vscode.window.showTextDocument(document, { preview: false }); + await vscode.commands.executeCommand("workbench.action.closeActiveEditor"); + await until( + "scratch completion document closing", + () => + !vscode.window.tabGroups.all.some((group) => + group.tabs.some( + (tab) => + tab.input instanceof vscode.TabInputText && tab.input.uri.fsPath === scratchPath, + ), + ), + 5000, + ); + } + } finally { + await fs.rm(scratchPath, { force: true }); + if (previousEditor) { + const options = { preview: false }; + if (previousViewColumn !== undefined) options.viewColumn = previousViewColumn; + const restored = await vscode.window.showTextDocument(previousEditor.document, options); + if (previousSelection) restored.selection = previousSelection; + } + } + } +} + +async function rootformLogContains(message) { + const logs = path.join(process.env.ROOTFORM_TEST_USER_DATA, "logs"); + for (const relative of await fs.readdir(logs, { recursive: true })) { + if (relative.endsWith("Rootform.log")) { + if ((await fs.readFile(path.join(logs, relative), "utf8")).includes(message)) return true; + } + } + return false; +} + +function referencePosition(document) { + const line = document + .getText() + .split(/\r?\n/) + .findIndex((text) => text.includes("concept.network")); + assert.notEqual(line, -1, "Expected local Concept reference in the test document."); + return new vscode.Position(line, document.lineAt(line).text.indexOf("network") + 1); +} + +async function run() { + const rootformBinary = process.env.ROOTFORM_BINARY; + const testRoot = process.env.ROOTFORM_TEST_ROOT; + assert.ok(rootformBinary, "ROOTFORM_BINARY was not passed to the extension host."); + assert.ok(testRoot, "ROOTFORM_TEST_ROOT was not passed to the extension host."); + await until( + "fixture workspace trust granted through VS Code", + () => vscode.workspace.isTrusted, + 60000, + ); + + const extension = vscode.extensions.getExtension("rootform-dev.rootform"); + assert.ok(extension, "Rootform extension did not load in the extension host."); + await extension.activate(); + + if (process.env.ROOTFORM_TEST_PHASE === "reopen") { + const rule = await openFile(path.join(testRoot, "first", "rule.rf.hcl")); + await until( + "saved workspace definition after reopening", + async () => + ( + await vscode.commands.executeCommand( + "vscode.executeDefinitionProvider", + rule.uri, + referencePosition(rule), + ) + )?.length > 0, + ); + await until( + "saved workspace without diagnostics", + () => vscode.languages.getDiagnostics(rule.uri).length === 0, + ); + console.log("Rootform workspace reopen passed."); + return; + } + if (process.env.ROOTFORM_TEST_PHASE === "standalone") { + assert.equal(vscode.workspace.workspaceFolders?.length ?? 0, 0); + const document = vscode.window.activeTextEditor?.document; + assert.ok(document); + assert.equal(document.languageId, "rootform"); + const source = document.getText(); + await replaceDocument(document, source.replace('version = "0.1.0"', 'version = "0.1"')); + await until( + "standalone file diagnostic", + () => vscode.languages.getDiagnostics(document.uri).length > 0, + ); + await replaceDocument(document, source); + await until( + "standalone source recovering", + () => vscode.languages.getDiagnostics(document.uri).length === 0, + ); + console.log("Rootform standalone file passed."); + return; + } + + const firstRoot = path.join(testRoot, "first"); + const secondRoot = path.join(testRoot, "second"); + const jsonRoot = path.join(testRoot, "json"); + const dialect = await openFile(path.join(firstRoot, "dialect.rf.hcl")); + assert.equal(dialect.languageId, "rootform"); + const rule = await openFile(path.join(firstRoot, "rule.rf.hcl")); + const peerDialect = await openFile(path.join(secondRoot, "dialect.rf.hcl")); + const jsonDialect = await openFile(path.join(jsonRoot, "dialect.rf.json")); + const policy = await openFile(path.join(testRoot, "policies", "checks.rf.hcl")); + + assert.equal( + vscode.workspace.workspaceFolders?.length, + 4, + "The fixture must open all workspace folders.", + ); + assert.equal( + jsonDialect.languageId, + "json", + "JSON source keeps VS Code's JSON editor presentation.", + ); + const settings = vscode.workspace.getConfiguration("rootform"); + assert.equal(path.resolve(settings.get("server.path")), path.resolve(rootformBinary)); + + await replaceDocument( + peerDialect, + peerDialect.getText().replace('version = "0.1.0"', 'version = "0.1"'), + ); + await until( + "a real Rootform diagnostic in the second workspace root", + () => vscode.languages.getDiagnostics(peerDialect.uri).length > 0, + ); + await replaceDocument( + peerDialect, + peerDialect.getText().replace('version = "0.1"', 'version = "0.1.0"'), + ); + await until( + "diagnostics clearing in the second workspace root", + () => vscode.languages.getDiagnostics(peerDialect.uri).length === 0, + ); + + await exerciseCompletionMatrix(firstRoot); + + await replaceDocument(dialect, dialect.getText().replace('version = "0.1.0"', 'version = "0.1"')); + await until( + "a real Rootform diagnostic in the first workspace root", + () => vscode.languages.getDiagnostics(dialect.uri).length > 0, + ); + assert.equal( + vscode.languages.getDiagnostics(peerDialect.uri).length, + 0, + "Root diagnostics must stay inside their workspace folder.", + ); + assert.equal( + vscode.languages.getDiagnostics(jsonDialect.uri).length, + 0, + "Root diagnostics must not leak into other workspace folders.", + ); + await replaceDocument(dialect, dialect.getText().replace('version = "0.1"', 'version = "0.1.0"')); + await until( + "diagnostics clearing after a valid edit", + () => vscode.languages.getDiagnostics(dialect.uri).length === 0, + ); + + await replaceDocument( + jsonDialect, + jsonDialect.getText().replace('"version": "0.1.0"', '"version": "0.1"'), + ); + await until( + "Rootform diagnostics for a JSON source document", + () => vscode.languages.getDiagnostics(jsonDialect.uri).length > 0, + ); + await replaceDocument( + jsonDialect, + jsonDialect.getText().replace('"version": "0.1"', '"version": "0.1.0"'), + ); + await until( + "diagnostics clearing for a JSON source document", + () => vscode.languages.getDiagnostics(jsonDialect.uri).length === 0, + ); + + const partialRule = rule.getText().replace("as=concept.network", "as=concept."); + await replaceDocument(rule, partialRule); + const completionLine = partialRule.split(/\r?\n/).findIndex((line) => line.includes("concept.")); + const completionPosition = new vscode.Position( + completionLine, + partialRule.split(/\r?\n/)[completionLine].length, + ); + const completionResult = await vscode.commands.executeCommand( + "vscode.executeCompletionItemProvider", + rule.uri, + completionPosition, + ); + const completions = Array.isArray(completionResult) + ? completionResult + : (completionResult?.items ?? []); + const networkCompletion = completions.find((item) => { + const label = completionLabel(item); + return label === "network" || label.endsWith(".network"); + }); + assert.ok(networkCompletion, "Rootform completion should offer the local Concept reference."); + assert.equal( + completions.some((item) => { + const label = completionLabel(item); + return ( + label === "service" || + label.endsWith(".service") || + label === "json-service" || + label.endsWith(".json-service") + ); + }), + false, + "Completion in the first root must not include a Concept from the second root.", + ); + + const completionEdit = new vscode.WorkspaceEdit(); + const textEdit = networkCompletion.textEdit; + if (textEdit && "range" in textEdit) { + completionEdit.replace(rule.uri, textEdit.range, textEdit.newText); + } else if (networkCompletion.range && networkCompletion.insertText) { + const range = + networkCompletion.range instanceof vscode.Range + ? networkCompletion.range + : networkCompletion.range.replacing; + completionEdit.replace(rule.uri, range, String(networkCompletion.insertText)); + } else if (networkCompletion.insertText) { + completionEdit.insert(rule.uri, completionPosition, String(networkCompletion.insertText)); + } else { + completionEdit.insert(rule.uri, completionPosition, String(networkCompletion.label)); + } + assert.equal( + await vscode.workspace.applyEdit(completionEdit), + true, + "Completion edit should apply to the document.", + ); + await until("completion text being applied", () => + rule.getText().includes("as=demo.concept.network"), + ); + assert.equal(rule.getText().includes("concept.concept."), false); + await until( + "completed source being valid", + () => vscode.languages.getDiagnostics(rule.uri).length === 0, + ); + + const beforeAmbiguousOwner = dialect.getText(); + await replaceDocument( + dialect, + beforeAmbiguousOwner + '\ndialect "other" { version = "0.1.0" }\n', + ); + await until( + "conflicting owner diagnostic", + () => vscode.languages.getDiagnostics(dialect.uri).length > 0, + ); + const ambiguousResult = await vscode.commands.executeCommand( + "vscode.executeCompletionItemProvider", + rule.uri, + referencePosition(rule), + ); + const ambiguousItems = Array.isArray(ambiguousResult) + ? ambiguousResult + : (ambiguousResult?.items ?? []); + assert.ok(ambiguousItems.some((item) => completionLabel(item).startsWith("rf."))); + assert.equal( + ambiguousItems.some((item) => completionLabel(item).startsWith("demo.")), + false, + "Completion must not choose an owner from conflicting headers in one file.", + ); + await replaceDocument(dialect, beforeAmbiguousOwner); + await until( + "owner conflict recovering", + () => vscode.languages.getDiagnostics(dialect.uri).length === 0, + ); + + const hover = await vscode.commands.executeCommand( + "vscode.executeHoverProvider", + rule.uri, + referencePosition(rule), + ); + assert.ok( + Array.isArray(hover) && hover.some((item) => item.contents?.length), + "Hover provider should return Rootform information.", + ); + const definitions = await vscode.commands.executeCommand( + "vscode.executeDefinitionProvider", + rule.uri, + referencePosition(rule), + ); + assert.ok( + Array.isArray(definitions) && definitions.length > 0, + "Definition provider should find the local Concept.", + ); + + const formatting = await vscode.commands.executeCommand( + "vscode.executeFormatDocumentProvider", + rule.uri, + { tabSize: 2, insertSpaces: true }, + ); + assert.ok( + Array.isArray(formatting) && formatting.length > 0, + "Formatter should offer edits for the deliberately unformatted fixture.", + ); + const formatEdit = new vscode.WorkspaceEdit(); + for (const item of formatting) formatEdit.replace(rule.uri, item.range, item.newText); + assert.equal( + await vscode.workspace.applyEdit(formatEdit), + true, + "Rootform formatting edits should apply.", + ); + await until("canonical formatting being applied", () => /^ match \{/m.test(rule.getText())); + + const peerBefore = peerDialect.getText(); + await replaceDocument(peerDialect, peerBefore.replace('version = "0.1.0"', 'version = "0.1"')); + await replaceDocument( + peerDialect, + peerDialect.getText().replace('version = "0.1"', 'version = "0.1.0"'), + ); + await replaceDocument( + dialect, + dialect + .getText() + .replace( + 'description = "Synthetic symbol for the VS Code integration fixture."', + 'description = "rapid edit one"', + ), + ); + await replaceDocument( + dialect, + dialect.getText().replace('description = "rapid edit one"', 'description = "rapid edit two"'), + ); + await fs.writeFile(path.join(firstRoot, "rootform.lock"), 'format_version: "1"\n'); + await fs.writeFile( + path.join(firstRoot, ".terraform.lock.hcl"), + "# Synthetic lock watcher fixture.\n", + ); + await until( + "both workspace roots remaining diagnostic-free", + () => + vscode.languages.getDiagnostics(dialect.uri).length === 0 && + vscode.languages.getDiagnostics(peerDialect.uri).length === 0 && + vscode.languages.getDiagnostics(jsonDialect.uri).length === 0 && + vscode.languages.getDiagnostics(rule.uri).length === 0, + ); + + // Policy source uses its compiler and can navigate a fully qualified authored symbol. + const policyDefinitions = await vscode.commands.executeCommand( + "vscode.executeDefinitionProvider", + policy.uri, + referencePosition(policy), + ); + assert.ok( + policyDefinitions?.some((item) => (item.uri ?? item.targetUri).fsPath === dialect.uri.fsPath), + ); + const policySource = policy.getText(); + await replaceDocument(policy, policySource.replace("demo.concept.network", "concept.network")); + await until( + "Policy compiler rejecting an unqualified target", + () => vscode.languages.getDiagnostics(policy.uri).length > 0, + ); + await replaceDocument(policy, policySource); + await until( + "Policy source recovering", + () => vscode.languages.getDiagnostics(policy.uri).length === 0, + ); + + // Temporary syntax failure must not poison subsequent documents or requests. + const ruleSource = rule.getText(); + await replaceDocument(rule, ruleSource + '\nrule "unfinished" {\n'); + await until( + "temporary syntax diagnostic", + () => vscode.languages.getDiagnostics(rule.uri).length > 0, + ); + await replaceDocument(rule, ruleSource); + await until("syntax recovery", () => vscode.languages.getDiagnostics(rule.uri).length === 0); + + // Closed sibling files are read from disk. Creation and deletion must both refresh references. + const networkBlock = /concept "network" \{[^}]*\}\n?/; + const declaration = dialect.getText().match(networkBlock)?.[0]; + assert.ok(declaration); + await replaceDocument(dialect, dialect.getText().replace(networkBlock, "")); + await dialect.save(); + await until("broken sibling reference", () => + vscode.languages.getDiagnostics(rule.uri).some((item) => item.code === "CONCEPT_UNKNOWN"), + ); + const newSibling = path.join(firstRoot, "network.rf.hcl"); + await fs.writeFile(newSibling, declaration); + await until( + "created sibling restoring reference", + () => vscode.languages.getDiagnostics(rule.uri).length === 0, + ); + await fs.unlink(newSibling); + await until("deleted sibling breaking reference", () => + vscode.languages.getDiagnostics(rule.uri).some((item) => item.code === "CONCEPT_UNKNOWN"), + ); + await fs.writeFile(newSibling, declaration); + await until( + "recreated sibling restoring reference", + () => vscode.languages.getDiagnostics(rule.uri).length === 0, + ); + await rule.save(); + await peerDialect.save(); + await jsonDialect.save(); + await policy.save(); + cp.execFileSync(rootformBinary, ["validate", "dialects", firstRoot, "--no-pager"], { + stdio: "pipe", + }); + + if (process.platform === "darwin" || process.platform === "linux") { + // A process that exits before initialize must fail once, then recover when + // the configured executable is corrected. Use a local recording fixture. + const incompatible = path.join(testRoot, "incompatible-server"); + await fs.writeFile(incompatible, '#!/bin/sh\nprintf "attempt\\n" >> "$0.attempts"\nexit 0\n'); + await fs.chmod(incompatible, 0o755); + await settings.update("server.path", incompatible, vscode.ConfigurationTarget.Global); + await until("incompatible executable attempted", async () => { + try { + return (await fs.readFile(`${incompatible}.attempts`, "utf8")).length > 0; + } catch { + return false; + } + }); + await delay(500); + assert.equal( + await fs.readFile(`${incompatible}.attempts`, "utf8"), + "attempt\n", + "A failed initial handshake must not start an automatic retry loop.", + ); + await until("incompatible handshake reported as failure", () => + rootformLogContains(`Rootform language server could not initialize from "${incompatible}"`), + ); + await settings.update("server.path", rootformBinary, vscode.ConfigurationTarget.Global); + await until( + "hover after correcting an incompatible executable", + async () => + ( + await vscode.commands.executeCommand( + "vscode.executeHoverProvider", + rule.uri, + referencePosition(rule), + ) + )?.length > 0, + ); + const stalled = path.join(testRoot, "stalled-server"); + await fs.writeFile(stalled, '#!/bin/sh\nprintf "%s" "$$" > "$0.pid"\nexec /bin/sleep 60\n'); + await fs.chmod(stalled, 0o755); + await settings.update("server.path", stalled, vscode.ConfigurationTarget.Global); + const stalledPid = await until("silent executable started", async () => { + try { + return Number(await fs.readFile(`${stalled}.pid`, "utf8")); + } catch { + return false; + } + }); + try { + await settings.update("server.path", rootformBinary, vscode.ConfigurationTarget.Global); + await until("silent initialize timeout reported with its cause", () => + rootformLogContains( + `Rootform language server did not initialize within 10 seconds from "${stalled}"`, + ), + ); + await until( + "silent initialize timing out and corrected path recovering", + async () => + ( + await vscode.commands.executeCommand( + "vscode.executeHoverProvider", + rule.uri, + referencePosition(rule), + ) + )?.length > 0, + ); + assert.throws(() => process.kill(stalledPid, 0), { code: "ESRCH" }); + } finally { + try { + process.kill(stalledPid, "SIGKILL"); + } catch (error) { + if (error.code !== "ESRCH") throw error; + } + } + const children = () => + cp + .execFileSync("ps", ["-axo", "pid=,ppid=,command="], { encoding: "utf8" }) + .split("\n") + .map((line) => /^\s*(\d+)\s+(\d+)\s+(.*)$/.exec(line)) + .filter(Boolean) + .filter( + (item) => + Number(item[2]) === process.pid && + item[3].includes(rootformBinary) && + item[3].endsWith(" lsp"), + ) + .map((item) => Number(item[1])); + const [serverPid] = await until( + "one running local Rootform child", + () => children().length === 1 && children(), + ); + process.kill(serverPid, "SIGKILL"); + await until( + "Rootform child restarting after process death", + () => children().length === 1 && children()[0] !== serverPid, + ); + await until( + "hover after process death", + async () => + ( + await vscode.commands.executeCommand( + "vscode.executeHoverProvider", + rule.uri, + referencePosition(rule), + ) + )?.length > 0, + ); + } + + await vscode.commands.executeCommand("rootform.restartLanguageServer"); + const postRestartHover = await vscode.commands.executeCommand( + "vscode.executeHoverProvider", + rule.uri, + referencePosition(rule), + ); + assert.ok( + Array.isArray(postRestartHover) && postRestartHover.length > 0, + "Providers should work after a serialized restart.", + ); +} + +module.exports = { + run: async () => { + try { + await run(); + console.log("Rootform real extension-host scenarios passed."); + } catch (error) { + console.error(error); + throw error; + } + }, +}; diff --git a/vscode/test/run-integration.cjs b/vscode/test/run-integration.cjs new file mode 100644 index 0000000..515202d --- /dev/null +++ b/vscode/test/run-integration.cjs @@ -0,0 +1,105 @@ +const assert = require("node:assert/strict"); +const fs = require("node:fs/promises"); +const os = require("node:os"); +const path = require("node:path"); +const { runTests } = require("@vscode/test-electron"); + +async function main() { + const vscodeExecutable = process.env.VSCODE_EXECUTABLE_PATH; + const rootformBinary = process.env.ROOTFORM_BINARY; + assert.ok(vscodeExecutable, "Set VSCODE_EXECUTABLE_PATH to the installed VS Code executable."); + assert.ok( + rootformBinary, + "Set ROOTFORM_BINARY to an explicitly provided local Rootform executable.", + ); + + const packageRoot = path.resolve(__dirname, ".."); + const temporaryRoot = await fs.mkdtemp(path.join(os.tmpdir(), "rootform-vscode-")); + const workspaceRoot = path.join(temporaryRoot, "workspace"); + const firstRoot = path.join(workspaceRoot, "first"); + const secondRoot = path.join(workspaceRoot, "second"); + const jsonRoot = path.join(workspaceRoot, "json"); + const policyRoot = path.join(workspaceRoot, "policies"); + const userDataDir = path.join(temporaryRoot, "user-data"); + const extensionsDir = path.join(temporaryRoot, "extensions"); + + try { + await fs.mkdir(firstRoot, { recursive: true }); + await fs.mkdir(secondRoot, { recursive: true }); + await fs.mkdir(jsonRoot, { recursive: true }); + await fs.mkdir(policyRoot, { recursive: true }); + await fs.mkdir(path.join(userDataDir, "User"), { recursive: true }); + await fs.mkdir(extensionsDir, { recursive: true }); + await fs.cp(path.join(packageRoot, "fixtures/integration/first"), firstRoot, { + recursive: true, + }); + await fs.cp(path.join(packageRoot, "fixtures/integration/second"), secondRoot, { + recursive: true, + }); + await fs.cp(path.join(packageRoot, "fixtures/integration/json"), jsonRoot, { recursive: true }); + + await fs.cp(path.join(packageRoot, "fixtures/integration/policies"), policyRoot, { + recursive: true, + }); + const workspaceFile = path.join(workspaceRoot, "rootform.code-workspace"); + await fs.writeFile( + workspaceFile, + JSON.stringify( + { + folders: [{ path: "first" }, { path: "second" }, { path: "json" }, { path: "policies" }], + }, + null, + 2, + ), + ); + await fs.writeFile( + path.join(userDataDir, "User/settings.json"), + JSON.stringify( + { + "rootform.server.path": path.resolve(rootformBinary), + }, + null, + 2, + ), + ); + + const runEditor = (entry, phase = "full") => + runTests({ + vscodeExecutablePath: path.resolve(vscodeExecutable), + extensionDevelopmentPath: packageRoot, + extensionTestsPath: path.join(__dirname, "extensionHost.cjs"), + extensionTestsEnv: { + ROOTFORM_BINARY: path.resolve(rootformBinary), + ROOTFORM_TEST_ROOT: workspaceRoot, + ROOTFORM_TEST_PHASE: phase, + ROOTFORM_TEST_USER_DATA: userDataDir, + }, + launchArgs: [ + entry, + "--disable-extensions", + "--user-data-dir", + userDataDir, + "--extensions-dir", + extensionsDir, + "--skip-welcome", + "--skip-release-notes", + ], + }); + await runEditor(workspaceFile); + await runEditor(workspaceFile, "reopen"); + const looseFile = path.join(temporaryRoot, "loose", "main.rf.hcl"); + await fs.mkdir(path.dirname(looseFile), { recursive: true }); + await fs.writeFile( + looseFile, + 'dialect "loose" { version = "0.1.0" }\nconcept "thing" { description = "Loose source." }\n', + ); + await runEditor(looseFile, "standalone"); + } finally { + await fs.rm(temporaryRoot, { recursive: true, force: true }); + } +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/vscode/test/serverController.test.cjs b/vscode/test/serverController.test.cjs new file mode 100644 index 0000000..d8bb054 --- /dev/null +++ b/vscode/test/serverController.test.cjs @@ -0,0 +1,148 @@ +const assert = require("node:assert/strict"); +const { test } = require("node:test"); +const { + MAX_RESTART_COUNT, + ServerController, + startupFailureMessage, +} = require("../out/serverController.js"); + +function deferred() { + let resolve; + const promise = new Promise((done) => { + resolve = done; + }); + return { promise, resolve }; +} + +function harness({ + trusted = true, + executable = "rootform", + createClient, + reportStartupFailure, + reportStopFailure, +} = {}) { + const state = { trusted, executable, created: [], startupFailures: [], stopFailures: [] }; + const controller = new ServerController({ + isTrusted: () => state.trusted, + executablePath: () => state.executable, + createClient: (path) => { + const client = createClient + ? createClient(path, state) + : { + start: async () => {}, + dispose: async () => {}, + }; + state.created.push({ path, client }); + return client; + }, + reportStartupFailure: (path, error) => { + state.startupFailures.push({ path, error }); + reportStartupFailure?.(path, error); + }, + reportStopFailure: (error) => { + state.stopFailures.push(error); + reportStopFailure?.(error); + }, + }); + return { controller, state }; +} + +test("serializes start and restart, stopping the old process before replacement", async () => { + const events = []; + const firstStart = deferred(); + let count = 0; + const { controller, state } = harness({ + createClient: () => { + const id = ++count; + return { + start: async () => { + events.push(`start-${id}`); + if (id === 1) await firstStart.promise; + events.push(`started-${id}`); + }, + dispose: async () => { + events.push(`stop-${id}`); + }, + }; + }, + }); + + const starting = controller.start(); + await Promise.resolve(); + state.executable = "/opt/rootform/rootform"; + const restarting = controller.restart(); + assert.deepEqual(events, ["start-1"]); + firstStart.resolve(); + await Promise.all([starting, restarting]); + assert.deepEqual(events, ["start-1", "started-1", "stop-1", "start-2", "started-2"]); + assert.deepEqual( + state.created.map(({ path }) => path), + ["rootform", "/opt/rootform/rootform"], + ); + await controller.dispose(); + assert.equal(events.at(-1), "stop-2"); +}); + +test("does not create a client until workspace trust is granted", async () => { + const { controller, state } = harness({ trusted: false }); + await controller.start(); + assert.equal(state.created.length, 0); + + state.trusted = true; + await controller.start(); + assert.equal(state.created.length, 1); + assert.equal(state.created[0].path, "rootform"); + + state.trusted = false; + await controller.restart(); + assert.equal(state.created.length, 1); + await controller.dispose(); +}); + +test("reports one actionable startup error without an automatic retry loop", async () => { + let starts = 0; + const { controller, state } = harness({ + createClient: () => ({ + start: async () => { + starts += 1; + throw Object.assign(new Error("missing"), { code: "ENOENT" }); + }, + dispose: async () => {}, + }), + }); + + await controller.start(); + assert.equal(starts, 1); + assert.equal(state.startupFailures.length, 1); + assert.match(startupFailureMessage("rootform", state.startupFailures[0].error), /not found/); + assert.equal(MAX_RESTART_COUNT, 4); + await controller.dispose(); +}); + +test("rejects an empty executable setting with a direct configuration fix", async () => { + const { controller, state } = harness({ executable: " " }); + await controller.start(); + assert.equal(state.created.length, 0); + assert.match(startupFailureMessage("", new Error()), /rootform\.server\.path/); + await controller.dispose(); +}); + +test("preserves the cause serialized by the pinned language-client spawn path", () => { + const executable = "/opt/Rootform Tools/rootform"; + const sdkError = (code) => + `Launching server using command ${executable} failed. Error: spawn ${executable} ${code}`; + assert.match(startupFailureMessage(executable, sdkError("ENOENT")), /was not found/); + assert.match(startupFailureMessage(executable, sdkError("EACCES")), /permissions/); + assert.match(startupFailureMessage(executable, sdkError("EPERM")), /permissions/); + assert.match( + startupFailureMessage(executable, "initialize response mentions ENOENT"), + /could not initialize/, + ); +}); + +test("names an initialization timeout and its executable remediation", () => { + const error = Object.assign(new Error("timeout"), { code: "ROOTFORM_LSP_INITIALIZE_TIMEOUT" }); + const message = startupFailureMessage("rootform", error); + assert.match(message, /did not initialize within 10 seconds/); + assert.match(message, /rootform\.server\.path/); +}); diff --git a/vscode/tsconfig.json b/vscode/tsconfig.json new file mode 100644 index 0000000..1d6b1ef --- /dev/null +++ b/vscode/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "Node16", + "moduleResolution": "Node16", + "lib": ["ES2022"], + "types": ["node", "vscode"], + "rootDir": "src", + "outDir": "out", + "strict": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + "noEmitOnError": true + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "out", "test", "fixtures"] +} diff --git a/zed/.gitignore b/zed/.gitignore new file mode 100644 index 0000000..5e7cbb5 --- /dev/null +++ b/zed/.gitignore @@ -0,0 +1,3 @@ +/target/ +/extension.wasm +/grammars/ diff --git a/zed/Cargo.lock b/zed/Cargo.lock new file mode 100644 index 0000000..9bb9625 --- /dev/null +++ b/zed/Cargo.lock @@ -0,0 +1,934 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aho-corasick" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" + +[[package]] +name = "auditable-serde" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7bf8143dfc3c0258df908843e169b5cc5fcf76c7718bd66135ef4a9cd558c5" +dependencies = [ + "semver", + "serde", + "serde_json", + "topological-sort", +] + +[[package]] +name = "bitflags" +version = "2.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" + +[[package]] +name = "cc" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f360145194ee8e21db5ee7f3fcd4fe52210864c75c985dae33218202c8bbe040" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" + +[[package]] +name = "crc32fast" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01a7799fd6b852db0e61728dde9a204c423b44d689dbd432522543614b490e78" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "displaydoc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "find-msvc-tools" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedcfb3409746eddb02b9e19ebda1c3394f759a152e48ee875a0844d1b955484" + +[[package]] +name = "flate2" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e634e2e0ebac1ee034020da1ca582e17ffe4e0f5e985823721e168928136dcb" +dependencies = [ + "crc32fast", + "miniz_oxide", + "zlib-rs", +] + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" + +[[package]] +name = "futures-executor" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" + +[[package]] +name = "futures-macro" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "futures-sink" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" + +[[package]] +name = "futures-task" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" + +[[package]] +name = "futures-util" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "icu_collections" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa68d21081c4a05d5a901a1c62add574c77048b6a1c67be3b50ce0b60d4ca513" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f9cf5f235641ed274641dd81c3f28d870e276763d0797aeeab72317b1c646f" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1563da1ed3e0b3bf3d74c9b85917ac9c56464d2f57242270c09c9e752f8021a0" + +[[package]] +name = "icu_properties" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e7ca276ad3145661a65914e6daf131ca5120cd3dcee8f8f3214b8875184a148" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa" + +[[package]] +name = "icu_provider" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "2.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", + "serde", + "serde_core", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "litemap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" + +[[package]] +name = "log" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "miniz_oxide" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63fbc4a50860e98e7b2aa7804ded1db5cbc3aff9193adaff57a6931bf7c4b4c" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "potential_utf" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" +dependencies = [ + "zerovec", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.119", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "rootform-zed" +version = "0.1.0" +dependencies = [ + "tree-sitter", + "tree-sitter-hcl", + "zed_extension_api", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "indexmap", + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "simd-adler32" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9395f0f0eee849a9b707b2f06bb92a6a422090e2123bb2ef8e87a0e61892a8e" + +[[package]] +name = "spdx" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e17e880bafaeb362a7b751ec46bdc5b61445a188f80e0606e68167cd540fa3" +dependencies = [ + "smallvec", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "tinystr" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "topological-sort" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d" + +[[package]] +name = "tree-sitter" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ac5ea5e7f2f1700842ec071401010b9c59bf735295f6e9fa079c3dc035b167" +dependencies = [ + "cc", + "regex", + "regex-syntax", + "serde_json", + "streaming-iterator", + "tree-sitter-language", +] + +[[package]] +name = "tree-sitter-hcl" +version = "1.2.0" +source = "git+https://github.com/tree-sitter-grammars/tree-sitter-hcl?rev=fad991865fee927dd1de5e172fb3f08ac674d914#fad991865fee927dd1de5e172fb3f08ac674d914" +dependencies = [ + "cc", + "tree-sitter-language", +] + +[[package]] +name = "tree-sitter-language" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca0d1bf6fdd806e43ae5198f82f527056d359def39e54e67a0f478ac09dac081" + +[[package]] +name = "unicode-ident" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "wasm-encoder" +version = "0.227.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80bb72f02e7fbf07183443b27b0f3d4144abf8c114189f2e088ed95b696a7822" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.227.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce1ef0faabbbba6674e97a56bee857ccddf942785a336c8b47b42373c922a91d" +dependencies = [ + "anyhow", + "auditable-serde", + "flate2", + "indexmap", + "serde", + "serde_derive", + "serde_json", + "spdx", + "url", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.227.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f51cad774fb3c9461ab9bccc9c62dfb7388397b5deda31bf40e8108ccd678b2" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + +[[package]] +name = "wit-bindgen" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10fb6648689b3929d56bbc7eb1acf70c9a42a29eb5358c67c10f54dbd5d695de" +dependencies = [ + "wit-bindgen-rt", + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92fa781d4f2ff6d3f27f3cc9b74a73327b31ca0dc4a3ef25a0ce2983e0e5af9b" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db52a11d4dfb0a59f194c064055794ee6564eb1ced88c25da2cf76e50c5621" +dependencies = [ + "bitflags", + "futures", + "once_cell", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d0809dc5ba19e2e98661bf32fc0addc5a3ca5bf3a6a7083aa6ba484085ff3ce" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn 2.0.119", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad19eec017904e04c60719592a803ee5da76cb51c81e3f6fbf9457f59db49799" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.119", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.227.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "635c3adc595422cbf2341a17fb73a319669cc8d33deed3a48368a841df86b676" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.227.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf445ed5157046e4baf56f9138c124a0824d4d1657e7204d71886ad8ce2fc11" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "writeable" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" + +[[package]] +name = "yoke" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec8ebde2db3681e8c9980cc27822030e68752690ddfa9473e739aeb4dbde6d71" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", + "synstructure", +] + +[[package]] +name = "zed_extension_api" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0729d50b4ca0a7e28e590bbe32e3ca0194d97ef654961451a424c661a366fca0" +dependencies = [ + "serde", + "serde_json", + "wit-bindgen", +] + +[[package]] +name = "zerofrom" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0464e17806c1d976d5cba29399c7f08e516e279e2ba493f63123b5fca67dd8" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "zlib-rs" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b268e58e7c693d7c271f93ffc4ba3b380412554231c85bf61ca7af91042a4112" + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/zed/Cargo.toml b/zed/Cargo.toml new file mode 100644 index 0000000..69140d6 --- /dev/null +++ b/zed/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "rootform-zed" +version = "0.1.0" +edition = "2021" +rust-version = "1.93.1" +license = "Apache-2.0" +publish = false + +[lib] +crate-type = ["cdylib"] + +[dependencies] +zed_extension_api = "=0.7.0" + +[dev-dependencies] +tree-sitter = "=0.25.3" +tree-sitter-hcl = { git = "https://github.com/tree-sitter-grammars/tree-sitter-hcl", rev = "fad991865fee927dd1de5e172fb3f08ac674d914" } diff --git a/zed/LICENSE b/zed/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/zed/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/zed/README.md b/zed/README.md new file mode 100644 index 0000000..703e9f0 --- /dev/null +++ b/zed/README.md @@ -0,0 +1,38 @@ +# Rootform for Zed + +The extension associates `.rf.hcl` files with Rootform syntax and starts the +existing `rootform lsp` server. Rootform owns parsing, diagnostics, completion, +navigation, and formatting; this package provides syntax presentation and LSP +transport. + +To try the package locally, open Zed's command palette, run `zed: install dev extension`, and select this directory. Configure an installed Rootform +CLI in Zed's settings: + +```json +{ + "lsp": { + "rootform": { + "binary": { + "path": "/absolute/path/to/rootform", + "arguments": ["lsp"] + } + } + } +} +``` + +When `binary.path` is configured, Zed launches that executable directly. Set +`binary.arguments` to `["lsp"]` as shown above; omitting arguments starts +Rootform without a subcommand. Zed also passes `binary.env` to the process and +owns launch errors for this override. + +Without `binary.path`, the extension finds `rootform` on Zed's worktree `PATH` +and supplies `["lsp"]`. A missing PATH executable produces a message with the +complete path-and-arguments setting. No server download or installation occurs. Use `editor: restart language server` +after correcting a failed launch or replacing the executable. + +Zed may need network access to prepare the pinned HCL grammar and `wasi-sdk` +while building the development extension. That preparation is separate from +runtime: the language server always comes from the local Rootform executable. +Tree-sitter syntax supplies bracket matching, indentation, and Zed's default +syntax folding. diff --git a/zed/THIRD_PARTY_NOTICES.md b/zed/THIRD_PARTY_NOTICES.md new file mode 100644 index 0000000..9e45f92 --- /dev/null +++ b/zed/THIRD_PARTY_NOTICES.md @@ -0,0 +1,44 @@ +# Third-party notices + +## tree-sitter-hcl + +The extension uses the HCL Tree-sitter grammar from +[`tree-sitter-grammars/tree-sitter-hcl`](https://github.com/tree-sitter-grammars/tree-sitter-hcl), +pinned in `extension.toml` to commit +[`fad991865fee927dd1de5e172fb3f08ac674d914`](https://github.com/tree-sitter-grammars/tree-sitter-hcl/tree/fad991865fee927dd1de5e172fb3f08ac674d914) +(v1.2.0). The upstream Apache License 2.0 text is retained at +[`licenses/tree-sitter-hcl-LICENSE`](licenses/tree-sitter-hcl-LICENSE), copied +from that exact commit's `LICENSE` file. + +## Rust runtime dependencies + +The WASM extension uses the following locked runtime dependencies. License +texts are retained below. Host-only procedural macros and test dependencies +are excluded from this runtime inventory. + +| Crate | Version | Retained license | +| --- | --- | --- | +| [bitflags](https://crates.io/crates/bitflags/2.13.2) | 2.13.2 | [MIT](licenses/bitflags-2.13.2-LICENSE-MIT) | +| [equivalent](https://crates.io/crates/equivalent/1.0.2) | 1.0.2 | [MIT](licenses/equivalent-1.0.2-LICENSE-MIT) | +| [futures](https://crates.io/crates/futures/0.3.34) | 0.3.34 | [MIT](licenses/futures-0.3.34-LICENSE-MIT) | +| [futures-channel](https://crates.io/crates/futures-channel/0.3.34) | 0.3.34 | [MIT](licenses/futures-channel-0.3.34-LICENSE-MIT) | +| [futures-core](https://crates.io/crates/futures-core/0.3.34) | 0.3.34 | [MIT](licenses/futures-core-0.3.34-LICENSE-MIT) | +| [futures-executor](https://crates.io/crates/futures-executor/0.3.34) | 0.3.34 | [MIT](licenses/futures-executor-0.3.34-LICENSE-MIT) | +| [futures-io](https://crates.io/crates/futures-io/0.3.34) | 0.3.34 | [MIT](licenses/futures-io-0.3.34-LICENSE-MIT) | +| [futures-sink](https://crates.io/crates/futures-sink/0.3.34) | 0.3.34 | [MIT](licenses/futures-sink-0.3.34-LICENSE-MIT) | +| [futures-task](https://crates.io/crates/futures-task/0.3.34) | 0.3.34 | [MIT](licenses/futures-task-0.3.34-LICENSE-MIT) | +| [futures-util](https://crates.io/crates/futures-util/0.3.34) | 0.3.34 | [MIT](licenses/futures-util-0.3.34-LICENSE-MIT) | +| [hashbrown](https://crates.io/crates/hashbrown/0.17.1) | 0.17.1 | [MIT](licenses/hashbrown-0.17.1-LICENSE-MIT) | +| [indexmap](https://crates.io/crates/indexmap/2.14.2) | 2.14.2 | [MIT](licenses/indexmap-2.14.2-LICENSE-MIT) | +| [itoa](https://crates.io/crates/itoa/1.0.18) | 1.0.18 | [MIT](licenses/itoa-1.0.18-LICENSE-MIT) | +| [memchr](https://crates.io/crates/memchr/2.8.3) | 2.8.3 | [MIT](licenses/memchr-2.8.3-LICENSE-MIT) | +| [once_cell](https://crates.io/crates/once_cell/1.21.4) | 1.21.4 | [MIT](licenses/once_cell-1.21.4-LICENSE-MIT) | +| [pin-project-lite](https://crates.io/crates/pin-project-lite/0.2.17) | 0.2.17 | [MIT](licenses/pin-project-lite-0.2.17-LICENSE-MIT) | +| [serde](https://crates.io/crates/serde/1.0.229) | 1.0.229 | [MIT](licenses/serde-1.0.229-LICENSE-MIT) | +| [serde_core](https://crates.io/crates/serde_core/1.0.229) | 1.0.229 | [MIT](licenses/serde_core-1.0.229-LICENSE-MIT) | +| [serde_json](https://crates.io/crates/serde_json/1.0.151) | 1.0.151 | [MIT](licenses/serde_json-1.0.151-LICENSE-MIT) | +| [slab](https://crates.io/crates/slab/0.4.12) | 0.4.12 | [MIT](licenses/slab-0.4.12-LICENSE) | +| [wit-bindgen](https://crates.io/crates/wit-bindgen/0.41.0) | 0.41.0 | [MIT](licenses/wit-bindgen-0.41.0-LICENSE-MIT) | +| [wit-bindgen-rt](https://crates.io/crates/wit-bindgen-rt/0.41.0) | 0.41.0 | [MIT](licenses/wit-bindgen-rt-0.41.0-LICENSE-MIT) | +| [zed_extension_api](https://crates.io/crates/zed_extension_api/0.7.0) | 0.7.0 | [Apache-2.0](licenses/zed_extension_api-0.7.0-LICENSE-APACHE) | +| [zmij](https://crates.io/crates/zmij/1.0.23) | 1.0.23 | [MIT](licenses/zmij-1.0.23-LICENSE-MIT) | diff --git a/zed/extension.toml b/zed/extension.toml new file mode 100644 index 0000000..2c317ff --- /dev/null +++ b/zed/extension.toml @@ -0,0 +1,15 @@ +id = "rootform" +name = "Rootform" +description = "Rootform language support for Zed." +version = "0.1.0" +schema_version = 1 +authors = ["Rootform"] +repository = "https://github.com/rootform-dev/editors" + +[language_servers.rootform] +name = "Rootform Language Server" +languages = ["Rootform"] + +[grammars.hcl] +repository = "https://github.com/tree-sitter-grammars/tree-sitter-hcl" +commit = "fad991865fee927dd1de5e172fb3f08ac674d914" diff --git a/zed/languages/rootform/brackets.scm b/zed/languages/rootform/brackets.scm new file mode 100644 index 0000000..76e3d2b --- /dev/null +++ b/zed/languages/rootform/brackets.scm @@ -0,0 +1,12 @@ +("(" @open ")" @close) +("[" @open "]" @close) +("{" @open "}" @close) + +((block_start) @open + (block_end) @close) + +((tuple_start) @open + (tuple_end) @close) + +((object_start) @open + (object_end) @close) diff --git a/zed/languages/rootform/config.toml b/zed/languages/rootform/config.toml new file mode 100644 index 0000000..1c151e6 --- /dev/null +++ b/zed/languages/rootform/config.toml @@ -0,0 +1,14 @@ +name = "Rootform" +grammar = "hcl" +path_suffixes = ["rf.hcl"] +line_comments = ["# ", "// "] +block_comment = ["/*", "*/"] +autoclose_before = ",}])" +tab_size = 2 +brackets = [ + { start = "{", end = "}", close = true, newline = true }, + { start = "[", end = "]", close = true, newline = true }, + { start = "(", end = ")", close = true, newline = true }, + { start = "\"", end = "\"", close = true, newline = false, not_in = ["comment", "string"] }, + { start = "/*", end = "*/", close = true, newline = false, not_in = ["comment", "string"] }, +] diff --git a/zed/languages/rootform/highlights.scm b/zed/languages/rootform/highlights.scm new file mode 100644 index 0000000..09a91b1 --- /dev/null +++ b/zed/languages/rootform/highlights.scm @@ -0,0 +1,76 @@ +[ + "!" + "*" + "/" + "%" + "+" + "-" + ">" + ">=" + "<" + "<=" + "==" + "!=" + "&&" + "||" +] @operator + +[ + "{" + "}" + "[" + "]" + "(" + ")" +] @punctuation.bracket + +["." ".*" "," "[*]"] @punctuation.delimiter +[ (ellipsis) "?" "=>" ] @punctuation.special +[ ":" "=" ] @punctuation + +["for" "endfor" "in" "if" "else" "endif"] @keyword + +[ + (quoted_template_start) + (quoted_template_end) + (template_literal) +] @string + +[ + (heredoc_identifier) + (heredoc_start) +] @punctuation.delimiter + +[ + (template_interpolation_start) + (template_interpolation_end) + (template_directive_start) + (template_directive_end) + (strip_marker) +] @punctuation.special + +(numeric_lit) @number +(bool_lit) @boolean +(null_lit) @constant +(comment) @comment +(identifier) @variable + +(function_call (identifier) @function) +(attribute (identifier) @property) + +(object_elem + key: (expression + (variable_expr + (identifier) @property))) + +(body + (block + (identifier) @keyword + (#any-of? @keyword "dialect" "concept" "context" "relation" "rule" "policy_pack" "policy"))) + +(body + (block + (body + (block + (identifier) @type + (#any-of? @type "provider" "match" "identity" "endpoint" "context" "relation" "contribution" "composition" "member" "target" "policy"))))) diff --git a/zed/languages/rootform/indents.scm b/zed/languages/rootform/indents.scm new file mode 100644 index 0000000..8bc215a --- /dev/null +++ b/zed/languages/rootform/indents.scm @@ -0,0 +1,12 @@ +[ + (block) + (object) + (tuple) + (function_call) +] @indent + +[ + "]" + "}" + ")" +] @outdent diff --git a/zed/licenses/bitflags-2.13.2-LICENSE-MIT b/zed/licenses/bitflags-2.13.2-LICENSE-MIT new file mode 100644 index 0000000..39d4bdb --- /dev/null +++ b/zed/licenses/bitflags-2.13.2-LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2014 The Rust Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/licenses/equivalent-1.0.2-LICENSE-MIT b/zed/licenses/equivalent-1.0.2-LICENSE-MIT new file mode 100644 index 0000000..5ac40da --- /dev/null +++ b/zed/licenses/equivalent-1.0.2-LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2016--2023 + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/licenses/futures-0.3.34-LICENSE-MIT b/zed/licenses/futures-0.3.34-LICENSE-MIT new file mode 100644 index 0000000..8ad082e --- /dev/null +++ b/zed/licenses/futures-0.3.34-LICENSE-MIT @@ -0,0 +1,26 @@ +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/licenses/futures-channel-0.3.34-LICENSE-MIT b/zed/licenses/futures-channel-0.3.34-LICENSE-MIT new file mode 100644 index 0000000..8ad082e --- /dev/null +++ b/zed/licenses/futures-channel-0.3.34-LICENSE-MIT @@ -0,0 +1,26 @@ +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/licenses/futures-core-0.3.34-LICENSE-MIT b/zed/licenses/futures-core-0.3.34-LICENSE-MIT new file mode 100644 index 0000000..8ad082e --- /dev/null +++ b/zed/licenses/futures-core-0.3.34-LICENSE-MIT @@ -0,0 +1,26 @@ +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/licenses/futures-executor-0.3.34-LICENSE-MIT b/zed/licenses/futures-executor-0.3.34-LICENSE-MIT new file mode 100644 index 0000000..8ad082e --- /dev/null +++ b/zed/licenses/futures-executor-0.3.34-LICENSE-MIT @@ -0,0 +1,26 @@ +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/licenses/futures-io-0.3.34-LICENSE-MIT b/zed/licenses/futures-io-0.3.34-LICENSE-MIT new file mode 100644 index 0000000..8ad082e --- /dev/null +++ b/zed/licenses/futures-io-0.3.34-LICENSE-MIT @@ -0,0 +1,26 @@ +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/licenses/futures-sink-0.3.34-LICENSE-MIT b/zed/licenses/futures-sink-0.3.34-LICENSE-MIT new file mode 100644 index 0000000..8ad082e --- /dev/null +++ b/zed/licenses/futures-sink-0.3.34-LICENSE-MIT @@ -0,0 +1,26 @@ +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/licenses/futures-task-0.3.34-LICENSE-MIT b/zed/licenses/futures-task-0.3.34-LICENSE-MIT new file mode 100644 index 0000000..8ad082e --- /dev/null +++ b/zed/licenses/futures-task-0.3.34-LICENSE-MIT @@ -0,0 +1,26 @@ +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/licenses/futures-util-0.3.34-LICENSE-MIT b/zed/licenses/futures-util-0.3.34-LICENSE-MIT new file mode 100644 index 0000000..8ad082e --- /dev/null +++ b/zed/licenses/futures-util-0.3.34-LICENSE-MIT @@ -0,0 +1,26 @@ +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/licenses/hashbrown-0.17.1-LICENSE-MIT b/zed/licenses/hashbrown-0.17.1-LICENSE-MIT new file mode 100644 index 0000000..5afc2a7 --- /dev/null +++ b/zed/licenses/hashbrown-0.17.1-LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2016 Amanieu d'Antras + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/licenses/indexmap-2.14.2-LICENSE-MIT b/zed/licenses/indexmap-2.14.2-LICENSE-MIT new file mode 100644 index 0000000..8b81810 --- /dev/null +++ b/zed/licenses/indexmap-2.14.2-LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2016--2017 + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/licenses/itoa-1.0.18-LICENSE-MIT b/zed/licenses/itoa-1.0.18-LICENSE-MIT new file mode 100644 index 0000000..31aa793 --- /dev/null +++ b/zed/licenses/itoa-1.0.18-LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/licenses/memchr-2.8.3-LICENSE-MIT b/zed/licenses/memchr-2.8.3-LICENSE-MIT new file mode 100644 index 0000000..3b0a5dc --- /dev/null +++ b/zed/licenses/memchr-2.8.3-LICENSE-MIT @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Andrew Gallant + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/zed/licenses/once_cell-1.21.4-LICENSE-MIT b/zed/licenses/once_cell-1.21.4-LICENSE-MIT new file mode 100644 index 0000000..31aa793 --- /dev/null +++ b/zed/licenses/once_cell-1.21.4-LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/licenses/pin-project-lite-0.2.17-LICENSE-MIT b/zed/licenses/pin-project-lite-0.2.17-LICENSE-MIT new file mode 100644 index 0000000..31aa793 --- /dev/null +++ b/zed/licenses/pin-project-lite-0.2.17-LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/licenses/serde-1.0.229-LICENSE-MIT b/zed/licenses/serde-1.0.229-LICENSE-MIT new file mode 100644 index 0000000..31aa793 --- /dev/null +++ b/zed/licenses/serde-1.0.229-LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/licenses/serde_core-1.0.229-LICENSE-MIT b/zed/licenses/serde_core-1.0.229-LICENSE-MIT new file mode 100644 index 0000000..31aa793 --- /dev/null +++ b/zed/licenses/serde_core-1.0.229-LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/licenses/serde_json-1.0.151-LICENSE-MIT b/zed/licenses/serde_json-1.0.151-LICENSE-MIT new file mode 100644 index 0000000..31aa793 --- /dev/null +++ b/zed/licenses/serde_json-1.0.151-LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/licenses/slab-0.4.12-LICENSE b/zed/licenses/slab-0.4.12-LICENSE new file mode 100644 index 0000000..819ce21 --- /dev/null +++ b/zed/licenses/slab-0.4.12-LICENSE @@ -0,0 +1,25 @@ +Copyright (c) 2019 Carl Lerche + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/licenses/tree-sitter-hcl-LICENSE b/zed/licenses/tree-sitter-hcl-LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/zed/licenses/tree-sitter-hcl-LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/zed/licenses/wit-bindgen-0.41.0-LICENSE-MIT b/zed/licenses/wit-bindgen-0.41.0-LICENSE-MIT new file mode 100644 index 0000000..31aa793 --- /dev/null +++ b/zed/licenses/wit-bindgen-0.41.0-LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/licenses/wit-bindgen-rt-0.41.0-LICENSE-MIT b/zed/licenses/wit-bindgen-rt-0.41.0-LICENSE-MIT new file mode 100644 index 0000000..31aa793 --- /dev/null +++ b/zed/licenses/wit-bindgen-rt-0.41.0-LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/licenses/zed_extension_api-0.7.0-LICENSE-APACHE b/zed/licenses/zed_extension_api-0.7.0-LICENSE-APACHE new file mode 100644 index 0000000..461a0fe --- /dev/null +++ b/zed/licenses/zed_extension_api-0.7.0-LICENSE-APACHE @@ -0,0 +1,222 @@ +Copyright 2022 - 2025 Zed Industries, Inc. + + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + + http://www.apache.org/licenses/LICENSE-2.0 + + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + + +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + + 1. Definitions. + + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + + END OF TERMS AND CONDITIONS diff --git a/zed/licenses/zmij-1.0.23-LICENSE-MIT b/zed/licenses/zmij-1.0.23-LICENSE-MIT new file mode 100644 index 0000000..31aa793 --- /dev/null +++ b/zed/licenses/zmij-1.0.23-LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/zed/rust-toolchain.toml b/zed/rust-toolchain.toml new file mode 100644 index 0000000..b2255c1 --- /dev/null +++ b/zed/rust-toolchain.toml @@ -0,0 +1,5 @@ +[toolchain] +channel = "1.93.1" +profile = "minimal" +components = ["rustfmt"] +targets = ["wasm32-wasip2"] diff --git a/zed/src/lib.rs b/zed/src/lib.rs new file mode 100644 index 0000000..beb598f --- /dev/null +++ b/zed/src/lib.rs @@ -0,0 +1,55 @@ +use zed::{Command, Extension, Worktree}; +use zed_extension_api as zed; + +struct RootformExtension; + +impl Extension for RootformExtension { + fn new() -> Self { + Self + } + + fn language_server_command( + &mut self, + _language_server_id: &zed::LanguageServerId, + worktree: &Worktree, + ) -> zed::Result { + // Zed handles binary.path, arguments and env overrides before this adapter. + command_from_path(worktree.which("rootform")) + } +} + +fn command_from_path(executable: Option) -> zed::Result { + let command = executable.ok_or_else(|| { + "Rootform executable was not found on Zed's PATH. Install a compatible Rootform CLI, or set `lsp.rootform.binary.path` and `lsp.rootform.binary.arguments` to [\"lsp\"] in Zed settings.".to_owned() + })?; + Ok(Command { + command, + args: vec!["lsp".to_owned()], + env: Vec::new(), + }) +} + +zed::register_extension!(RootformExtension); + +#[cfg(test)] +mod tests { + use super::command_from_path; + + #[test] + fn path_executable_is_launched_directly_with_lsp() { + let command = command_from_path(Some("/opt/Rootform Tools/rootform".to_owned())) + .expect("local executable should be selected"); + assert_eq!(command.command, "/opt/Rootform Tools/rootform"); + assert_eq!(command.args, ["lsp"]); + assert!(command.env.is_empty()); + } + + #[test] + fn missing_path_executable_gives_complete_native_override_remediation() { + let error = command_from_path(None).expect_err("missing executable must stop startup"); + assert!(error.contains("Zed's PATH")); + assert!(error.contains("lsp.rootform.binary.path")); + assert!(error.contains("lsp.rootform.binary.arguments")); + assert!(error.contains("[\"lsp\"]")); + } +} diff --git a/zed/tests/syntax.rs b/zed/tests/syntax.rs new file mode 100644 index 0000000..c66e8df --- /dev/null +++ b/zed/tests/syntax.rs @@ -0,0 +1,180 @@ +use std::collections::BTreeSet; + +use tree_sitter::{Language, Parser, Query, QueryCursor, StreamingIterator, Tree}; + +const HIGHLIGHTS_QUERY: &str = include_str!("../languages/rootform/highlights.scm"); +const BRACKETS_QUERY: &str = include_str!("../languages/rootform/brackets.scm"); +const INDENTS_QUERY: &str = include_str!("../languages/rootform/indents.scm"); + +const SAMPLE_HCL: &str = r#" +dialect "demo" { + version = "0.1.0" + enabled = true + nullable = null + label = upper("rootform") + values = [1, 2] + settings = { retries = 2 } + + provider "local" { + endpoint = "http://localhost" + } +} +"#; + +fn hcl_language() -> Language { + tree_sitter_hcl::LANGUAGE.into() +} + +fn parse_sample(language: &Language) -> Tree { + let mut parser = Parser::new(); + parser + .set_language(language) + .expect("the pinned HCL grammar should load"); + + let tree = parser + .parse(SAMPLE_HCL, None) + .expect("the sample source should produce a syntax tree"); + assert!( + !tree.root_node().has_error(), + "sample HCL should parse without errors: {}", + tree.root_node().to_sexp() + ); + tree +} + +fn capture_names(query: &Query, tree: &Tree) -> BTreeSet { + let mut cursor = QueryCursor::new(); + let mut names = BTreeSet::new(); + + let mut matches = cursor.matches(query, tree.root_node(), SAMPLE_HCL.as_bytes()); + while let Some(query_match) = matches.next() { + for capture in query_match.captures { + names.insert(query.capture_names()[capture.index as usize].to_owned()); + } + } + + names +} + +fn assert_captures(query: &Query, tree: &Tree, expected: &[&str]) { + let actual = capture_names(query, tree); + for name in expected { + assert!( + actual.contains(*name), + "expected capture @{name}; actual captures: {actual:?}" + ); + } +} + +#[test] +fn all_shipped_queries_compile_against_the_pinned_hcl_grammar() { + let language = hcl_language(); + for (name, source) in [ + ("highlights", HIGHLIGHTS_QUERY), + ("brackets", BRACKETS_QUERY), + ("indents", INDENTS_QUERY), + ] { + Query::new(&language, source) + .unwrap_or_else(|error| panic!("{name} query failed to compile: {error:?}")); + } +} + +#[test] +fn shipped_queries_capture_representative_error_free_hcl() { + let language = hcl_language(); + let tree = parse_sample(&language); + + let highlights = Query::new(&language, HIGHLIGHTS_QUERY) + .expect("highlights query should compile against the pinned HCL grammar"); + assert_captures( + &highlights, + &tree, + &[ + "keyword", "type", "property", "function", "string", "boolean", "constant", "number", + ], + ); + + let brackets = Query::new(&language, BRACKETS_QUERY) + .expect("brackets query should compile against the pinned HCL grammar"); + assert_captures(&brackets, &tree, &["open", "close"]); + + let indents = Query::new(&language, INDENTS_QUERY) + .expect("indents query should compile against the pinned HCL grammar"); + assert_captures(&indents, &tree, &["indent", "outdent"]); +} + +#[test] +fn every_rootform_block_keyword_has_a_highlight() { + let source = r#" +dialect "demo" { + provider "hashicorp/local" {} +} +concept "service" {} +context "network" {} +relation "uses" {} +policy_pack "checks" {} +policy "check" { + target {} +} +rule "service" { + match {} + identity {} + endpoint {} + context {} + relation {} + contribution {} + composition { + member "part" { + match {} + } + } +} +"#; + let language = hcl_language(); + let mut parser = Parser::new(); + parser.set_language(&language).unwrap(); + let tree = parser.parse(source, None).unwrap(); + assert!(!tree.root_node().has_error()); + let query = Query::new(&language, HIGHLIGHTS_QUERY).unwrap(); + let mut cursor = QueryCursor::new(); + let mut highlighted = BTreeSet::new(); + let mut matches = cursor.matches(&query, tree.root_node(), source.as_bytes()); + while let Some(found) = matches.next() { + for capture in found.captures { + if matches!( + query.capture_names()[capture.index as usize], + "keyword" | "type" + ) { + highlighted.insert( + capture + .node + .utf8_text(source.as_bytes()) + .unwrap() + .to_owned(), + ); + } + } + } + for name in [ + "dialect", + "provider", + "concept", + "context", + "relation", + "policy_pack", + "policy", + "target", + "rule", + "match", + "identity", + "endpoint", + "contribution", + "composition", + "member", + ] { + assert!( + highlighted.contains(name), + "unhighlighted Rootform block: {name}" + ); + } +}