Detailed changes
@@ -508,7 +508,7 @@ dependencies = [
"futures-lite 2.2.0",
"parking",
"polling 3.3.2",
- "rustix 0.38.30",
+ "rustix 0.38.32",
"slab",
"tracing",
"windows-sys 0.52.0",
@@ -610,7 +610,7 @@ dependencies = [
"cfg-if",
"event-listener 5.1.0",
"futures-lite 2.2.0",
- "rustix 0.38.30",
+ "rustix 0.38.32",
"windows-sys 0.52.0",
]
@@ -648,7 +648,7 @@ dependencies = [
"cfg-if",
"futures-core",
"futures-io",
- "rustix 0.38.30",
+ "rustix 0.38.32",
"signal-hook-registry",
"slab",
"windows-sys 0.48.0",
@@ -1702,7 +1702,7 @@ dependencies = [
"bitflags 2.4.2",
"log",
"polling 3.3.2",
- "rustix 0.38.30",
+ "rustix 0.38.32",
"slab",
"thiserror",
]
@@ -1714,16 +1714,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f0ea9b9476c7fad82841a8dbb380e2eae480c21910feba80725b46931ed8f02"
dependencies = [
"calloop",
- "rustix 0.38.30",
+ "rustix 0.38.32",
"wayland-backend",
"wayland-client",
]
[[package]]
name = "cap-fs-ext"
-version = "2.0.1"
+version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88e341d15ac1029aadce600be764a1a1edafe40e03cde23285bc1d261b3a4866"
+checksum = "769f8cd02eb04d57f14e2e371ebb533f96817f9b2525d73a5c72b61ca7973747"
dependencies = [
"cap-primitives",
"cap-std",
@@ -1733,21 +1733,21 @@ dependencies = [
[[package]]
name = "cap-net-ext"
-version = "2.0.1"
+version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "434168fe6533055f0f4204039abe3ff6d7db338ef46872a5fa39e9d5ad5ab7a9"
+checksum = "59ff6d3fb274292a9af283417e383afe6ded1fe66f6472d2c781216d3d80c218"
dependencies = [
"cap-primitives",
"cap-std",
- "rustix 0.38.30",
+ "rustix 0.38.32",
"smallvec",
]
[[package]]
name = "cap-primitives"
-version = "2.0.1"
+version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe16767ed8eee6d3f1f00d6a7576b81c226ab917eb54b96e5f77a5216ef67abb"
+checksum = "90a0b44fc796b1a84535a63753d50ba3972c4db55c7255c186f79140e63d56d0"
dependencies = [
"ambient-authority",
"fs-set-times",
@@ -1755,16 +1755,16 @@ dependencies = [
"io-lifetimes 2.0.3",
"ipnet",
"maybe-owned",
- "rustix 0.38.30",
+ "rustix 0.38.32",
"windows-sys 0.52.0",
"winx",
]
[[package]]
name = "cap-rand"
-version = "2.0.1"
+version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20e5695565f0cd7106bc3c7170323597540e772bb73e0be2cd2c662a0f8fa4ca"
+checksum = "4327f08daac33a99bb03c54ae18c8f32c3ba31c728a33ddf683c6c6a5043de68"
dependencies = [
"ambient-authority",
"rand 0.8.5",
@@ -1772,27 +1772,27 @@ dependencies = [
[[package]]
name = "cap-std"
-version = "2.0.1"
+version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "593db20e4c51f62d3284bae7ee718849c3214f93a3b94ea1899ad85ba119d330"
+checksum = "266626ce180cf9709f317d0bf9754e3a5006359d87f4bf792f06c9c5f1b63c0f"
dependencies = [
"cap-primitives",
"io-extras",
"io-lifetimes 2.0.3",
- "rustix 0.38.30",
+ "rustix 0.38.32",
]
[[package]]
name = "cap-time-ext"
-version = "2.0.1"
+version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03261630f291f425430a36f38c847828265bc928f517cdd2004c56f4b02f002b"
+checksum = "e1353421ba83c19da60726e35db0a89abef984b3be183ff6f58c5b8084fcd0c5"
dependencies = [
"ambient-authority",
"cap-primitives",
"iana-time-zone",
"once_cell",
- "rustix 0.38.30",
+ "rustix 0.38.32",
"winx",
]
@@ -2604,9 +2604,9 @@ dependencies = [
[[package]]
name = "cpp_demangle"
-version = "0.3.5"
+version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eeaa953eaad386a53111e47172c2fedba671e5684c8dd601a5f474f4f118710f"
+checksum = "7e8227005286ec39567949b33df9896bcadfa6051bccca2488129f108ca23119"
dependencies = [
"cfg-if",
]
@@ -2622,18 +2622,18 @@ dependencies = [
[[package]]
name = "cranelift-bforest"
-version = "0.105.2"
+version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9515fcc42b6cb5137f76b84c1a6f819782d0cf12473d145d3bc5cd67eedc8bc2"
+checksum = "6a535eb1cf5a6003197dc569320c40c1cb2d2f97ef5d5348eebf067f20957381"
dependencies = [
"cranelift-entity",
]
[[package]]
name = "cranelift-codegen"
-version = "0.105.2"
+version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ad827c6071bfe6d22de1bc331296a29f9ddc506ff926d8415b435ec6a6efce0"
+checksum = "11b5066db32cec1492573827183af2142d2d88fe85a83cfc9e73f0f63d3788d4"
dependencies = [
"bumpalo",
"cranelift-bforest",
@@ -2652,33 +2652,33 @@ dependencies = [
[[package]]
name = "cranelift-codegen-meta"
-version = "0.105.2"
+version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10e6b36237a9ca2ce2fb4cc7741d418a080afa1327402138412ef85d5367bef1"
+checksum = "64942e5774308e835fbad4dd25f253105412c90324631910e1ec27963147bddb"
dependencies = [
"cranelift-codegen-shared",
]
[[package]]
name = "cranelift-codegen-shared"
-version = "0.105.2"
+version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c36bf4bfb86898a94ccfa773a1f86e8a5346b1983ff72059bdd2db4600325251"
+checksum = "c39c33db9a86dd6d8d04166a10c53deb477aeea3500eaaefca682e4eda9bb986"
[[package]]
name = "cranelift-control"
-version = "0.105.2"
+version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7cbf36560e7a6bd1409ca91e7b43b2cc7ed8429f343d7605eadf9046e8fac0d0"
+checksum = "4b7fc4937613aea3156a0538800a17bf56f345a5da2e79ae3df58488c93d867f"
dependencies = [
"arbitrary",
]
[[package]]
name = "cranelift-entity"
-version = "0.105.2"
+version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a71e11061a75b1184c09bea97c026a88f08b59ade96a7bb1f259d4ea0df2e942"
+checksum = "f85575e79a153ce1ddbfb7fe1813519b4bfe1eb200cc9c8353b45ad123ae4d36"
dependencies = [
"serde",
"serde_derive",
@@ -2686,9 +2686,9 @@ dependencies = [
[[package]]
name = "cranelift-frontend"
-version = "0.105.2"
+version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af5d4da63143ee3485c7bcedde0a818727d737d1083484a0ceedb8950c89e495"
+checksum = "bbc31d6c0ab2249fe0c21e988256b42f5f401ab2673b4fc40076c82a698bdfb9"
dependencies = [
"cranelift-codegen",
"log",
@@ -2698,15 +2698,15 @@ dependencies = [
[[package]]
name = "cranelift-isle"
-version = "0.105.2"
+version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "457a9832b089e26f5eea70dcf49bed8ec6edafed630ce7c83161f24d46ab8085"
+checksum = "dc14f37e3314c0e4c53779c2f46753bf242efff76ee9473757a1fff3b495ad37"
[[package]]
name = "cranelift-native"
-version = "0.105.2"
+version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b490d579df1ce365e1ea359e24ed86d82289fa785153327c2f6a69a59a731e4"
+checksum = "2ea5375f76ab31f9800a23fb2b440810286a6f669a3eb467cdd7ff255ea64268"
dependencies = [
"cranelift-codegen",
"libc",
@@ -2715,14 +2715,14 @@ dependencies = [
[[package]]
name = "cranelift-wasm"
-version = "0.105.2"
+version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8cd747ed7f9a461dda9c388415392f6bb95d1a6ef3b7694d17e0817eb74b7798"
+checksum = "79851dba01b1fa83fad95134aa27beca88dc4b027121d92ab19788582389dc5f"
dependencies = [
"cranelift-codegen",
"cranelift-entity",
"cranelift-frontend",
- "itertools 0.10.5",
+ "itertools 0.12.1",
"log",
"smallvec",
"wasmparser",
@@ -3498,7 +3498,7 @@ dependencies = [
"wasmparser",
"wasmtime",
"wasmtime-wasi",
- "wit-component 0.20.3",
+ "wit-component",
]
[[package]]
@@ -3589,7 +3589,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e5768da2206272c81ef0b5e951a41862938a6070da63bcea197899942d3b947"
dependencies = [
"cfg-if",
- "rustix 0.38.30",
+ "rustix 0.38.32",
"windows-sys 0.52.0",
]
@@ -3901,7 +3901,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "033b337d725b97690d86893f9de22b67b80dcc4e9ad815f348254c38119db8fb"
dependencies = [
"io-lifetimes 2.0.3",
- "rustix 0.38.30",
+ "rustix 0.38.32",
"windows-sys 0.52.0",
]
@@ -5000,6 +5000,15 @@ dependencies = [
"either",
]
+[[package]]
+name = "itertools"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
+dependencies = [
+ "either",
+]
+
[[package]]
name = "itoa"
version = "1.0.9"
@@ -5284,7 +5293,6 @@ dependencies = [
"tree-sitter-elm",
"tree-sitter-embedded-template",
"tree-sitter-erlang",
- "tree-sitter-gleam",
"tree-sitter-glsl",
"tree-sitter-go",
"tree-sitter-gomod",
@@ -5310,7 +5318,6 @@ dependencies = [
"tree-sitter-ruby",
"tree-sitter-rust",
"tree-sitter-scheme",
- "tree-sitter-svelte",
"tree-sitter-toml",
"tree-sitter-typescript",
"tree-sitter-vue",
@@ -5697,7 +5704,7 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64"
dependencies = [
- "rustix 0.38.30",
+ "rustix 0.38.32",
]
[[package]]
@@ -6884,7 +6891,7 @@ dependencies = [
"cfg-if",
"concurrent-queue",
"pin-project-lite",
- "rustix 0.38.30",
+ "rustix 0.38.32",
"tracing",
"windows-sys 0.52.0",
]
@@ -7939,9 +7946,9 @@ dependencies = [
[[package]]
name = "rustix"
-version = "0.38.30"
+version = "0.38.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca"
+checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89"
dependencies = [
"bitflags 2.4.2",
"errno",
@@ -7960,7 +7967,7 @@ checksum = "a25c3aad9fc1424eb82c88087789a7d938e1829724f3e4043163baf0d13cfc12"
dependencies = [
"errno",
"libc",
- "rustix 0.38.30",
+ "rustix 0.38.32",
]
[[package]]
@@ -8712,7 +8719,7 @@ dependencies = [
"libc",
"log",
"memmap2 0.9.4",
- "rustix 0.38.30",
+ "rustix 0.38.32",
"thiserror",
"wayland-backend",
"wayland-client",
@@ -9368,16 +9375,16 @@ dependencies = [
[[package]]
name = "system-interface"
-version = "0.26.1"
+version = "0.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0682e006dd35771e392a6623ac180999a9a854b1d4a6c12fb2e804941c2b1f58"
+checksum = "9aef1f9d4c1dbdd1cb3a63be9efd2f04d8ddbc919d46112982c76818ffc2f1a7"
dependencies = [
"bitflags 2.4.2",
"cap-fs-ext",
"cap-std",
"fd-lock",
"io-lifetimes 2.0.3",
- "rustix 0.38.30",
+ "rustix 0.38.32",
"windows-sys 0.52.0",
"winx",
]
@@ -9466,7 +9473,7 @@ dependencies = [
"cfg-if",
"fastrand 2.0.0",
"redox_syscall 0.4.1",
- "rustix 0.38.30",
+ "rustix 0.38.32",
"windows-sys 0.52.0",
]
@@ -10109,11 +10116,10 @@ dependencies = [
[[package]]
name = "tree-sitter"
version = "0.20.100"
-source = "git+https://github.com/tree-sitter/tree-sitter?rev=4294e59279205f503eb14348dd5128bd5910c8fb#4294e59279205f503eb14348dd5128bd5910c8fb"
+source = "git+https://github.com/tree-sitter/tree-sitter?rev=05079ae3d1bc44bedc4594eef925b36ba5e317a2#05079ae3d1bc44bedc4594eef925b36ba5e317a2"
dependencies = [
"cc",
"regex",
- "wasmtime",
"wasmtime-c-api-impl",
]
@@ -10237,15 +10243,6 @@ dependencies = [
"tree-sitter",
]
-[[package]]
-name = "tree-sitter-gleam"
-version = "0.34.0"
-source = "git+https://github.com/gleam-lang/tree-sitter-gleam?rev=58b7cac8fc14c92b0677c542610d8738c373fa81#58b7cac8fc14c92b0677c542610d8738c373fa81"
-dependencies = [
- "cc",
- "tree-sitter",
-]
-
[[package]]
name = "tree-sitter-glsl"
version = "0.1.4"
@@ -10488,15 +10485,6 @@ dependencies = [
"tree-sitter",
]
-[[package]]
-name = "tree-sitter-svelte"
-version = "0.10.2"
-source = "git+https://github.com/Himujjal/tree-sitter-svelte?rev=bd60db7d3d06f89b6ec3b287c9a6e9190b5564bd#bd60db7d3d06f89b6ec3b287c9a6e9190b5564bd"
-dependencies = [
- "cc",
- "tree-sitter",
-]
-
[[package]]
name = "tree-sitter-toml"
version = "0.5.1"
@@ -11031,32 +11019,6 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
-[[package]]
-name = "wasi-common"
-version = "18.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "880c1461417b2bf90262591bf8a5f04358fb86dac8a585a49b87024971296763"
-dependencies = [
- "anyhow",
- "bitflags 2.4.2",
- "cap-fs-ext",
- "cap-rand",
- "cap-std",
- "cap-time-ext",
- "fs-set-times",
- "io-extras",
- "io-lifetimes 2.0.3",
- "log",
- "once_cell",
- "rustix 0.38.30",
- "system-interface",
- "thiserror",
- "tracing",
- "wasmtime",
- "wiggle",
- "windows-sys 0.52.0",
-]
-
[[package]]
name = "wasm-bindgen"
version = "0.2.87"
@@ -11125,18 +11087,18 @@ checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
[[package]]
name = "wasm-encoder"
-version = "0.41.2"
+version = "0.201.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "972f97a5d8318f908dded23594188a90bcd09365986b1163e66d70170e5287ae"
+checksum = "b9c7d2731df60006819b013f64ccc2019691deccf6e11a1804bc850cd6748f1a"
dependencies = [
"leb128",
]
[[package]]
name = "wasm-metadata"
-version = "0.10.20"
+version = "0.201.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18ebaa7bd0f9e7a5e5dd29b9a998acf21c4abed74265524dd7e85934597bfb10"
+checksum = "0fd83062c17b9f4985d438603cde0a5e8c5c8198201a6937f778b607924c7da2"
dependencies = [
"anyhow",
"indexmap 2.0.0",
@@ -11150,9 +11112,9 @@ dependencies = [
[[package]]
name = "wasmparser"
-version = "0.121.2"
+version = "0.201.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9dbe55c8f9d0dbd25d9447a5a889ff90c0cc3feaa7395310d3d826b2c703eaab"
+checksum = "84e5df6dba6c0d7fafc63a450f1738451ed7a0b52295d83e868218fa286bf708"
dependencies = [
"bitflags 2.4.2",
"indexmap 2.0.0",
@@ -11161,9 +11123,9 @@ dependencies = [
[[package]]
name = "wasmprinter"
-version = "0.2.80"
+version = "0.201.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60e73986a6b7fdfedb7c5bf9e7eb71135486507c8fbc4c0c42cffcb6532988b7"
+checksum = "a67e66da702706ba08729a78e3c0079085f6bfcb1a62e4799e97bbf728c2c265"
dependencies = [
"anyhow",
"wasmparser",
@@ -11171,9 +11133,9 @@ dependencies = [
[[package]]
name = "wasmtime"
-version = "18.0.2"
+version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c843b8bc4dd4f3a76173ba93405c71111d570af0d90ea5f6299c705d0c2add2"
+checksum = "6a08af88fa3d324cc5cf6d388d90ef396a787b3fb4bbd51ba185f8645dc0f02c"
dependencies = [
"anyhow",
"async-trait",
@@ -11188,7 +11150,8 @@ dependencies = [
"object",
"once_cell",
"paste",
- "rustix 0.38.30",
+ "rustix 0.38.32",
+ "semver",
"serde",
"serde_derive",
"serde_json",
@@ -11201,24 +11164,25 @@ dependencies = [
"wasmtime-fiber",
"wasmtime-jit-icache-coherence",
"wasmtime-runtime",
+ "wasmtime-slab",
"wasmtime-winch",
"windows-sys 0.52.0",
]
[[package]]
name = "wasmtime-asm-macros"
-version = "18.0.2"
+version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86b9d329c718b3a18412a6a017c912b539baa8fe1210d21b651f6b4dbafed743"
+checksum = "16cdbfcf28542bcda0b5fd68d44603e53e5ad126cbe7b9f25c130e1249fd8211"
dependencies = [
"cfg-if",
]
[[package]]
name = "wasmtime-c-api-impl"
-version = "18.0.2"
+version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc93587c24d8e3cb28912eb7abf95f7e350380656faccc46cff04c0821ec58c2"
+checksum = "67dea28073e105735210b9e932b5e654198d5e28ed31f1314037cd7664ceda2b"
dependencies = [
"anyhow",
"log",
@@ -11230,9 +11194,9 @@ dependencies = [
[[package]]
name = "wasmtime-c-api-macros"
-version = "18.0.2"
+version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e571a71eba52dfe81ef653a3a336888141f00fc2208a9962722e036fe2a34be"
+checksum = "0cfe12050fa28b17ab8434ab757fee281dd0d5c7715fa1bc5e4c0b29d1705415"
dependencies = [
"proc-macro2",
"quote",
@@ -11240,9 +11204,9 @@ dependencies = [
[[package]]
name = "wasmtime-component-macro"
-version = "18.0.2"
+version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8d55ddfd02898885c39638eae9631cd430c83a368f5996ed0f7bfb181d02157"
+checksum = "0cdcf690257c623506eeec3a502864b282aab0fdfd6981c1ebb63c7e98f4a23a"
dependencies = [
"anyhow",
"proc-macro2",
@@ -11250,20 +11214,20 @@ dependencies = [
"syn 2.0.48",
"wasmtime-component-util",
"wasmtime-wit-bindgen",
- "wit-parser 0.13.2",
+ "wit-parser",
]
[[package]]
name = "wasmtime-component-util"
-version = "18.0.2"
+version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d6d69c430cddc70ec42159506962c66983ce0192ebde4eb125b7aabc49cff88"
+checksum = "ab3ae7bf66e2fae1e332ab3634f332d7422e878a6eecc47c8f8f78cc1f24e501"
[[package]]
name = "wasmtime-cranelift"
-version = "18.0.2"
+version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31ca62f519225492bd555d0ec85a2dacb0c10315db3418c8b9aeb3824bf54a24"
+checksum = "67ea025c969a09117818732fa6f96848e858a7953d4659dab8081a6eea3c0523"
dependencies = [
"anyhow",
"cfg-if",
@@ -11286,9 +11250,9 @@ dependencies = [
[[package]]
name = "wasmtime-cranelift-shared"
-version = "18.0.2"
+version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd5f2071f42e61490bf7cb95b9acdbe6a29dd577a398019304a960585f28b844"
+checksum = "dcd6dd2f8d8d4860b384f61f89b597633a5b5f0943c546210e5084c5d321fe20"
dependencies = [
"anyhow",
"cranelift-codegen",
@@ -11302,9 +11266,9 @@ dependencies = [
[[package]]
name = "wasmtime-environ"
-version = "18.0.2"
+version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82bf1a47f384610da19f58b0fd392ca6a3b720974315c08afb0392c0f3951fed"
+checksum = "7f60f3f717658dd77745de03b750d5852126e9be6dad465848c77f90387c44c9"
dependencies = [
"anyhow",
"bincode",
@@ -11328,14 +11292,14 @@ dependencies = [
[[package]]
name = "wasmtime-fiber"
-version = "18.0.2"
+version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e31aecada2831e067ebfe93faa3001cc153d506f8af40bbea58aa1d20fe4820"
+checksum = "bf8cd22ab1041bf0e54b6283e57824557902e4fed8b1f3a7eef29cbaba89eebf"
dependencies = [
"anyhow",
"cc",
"cfg-if",
- "rustix 0.38.30",
+ "rustix 0.38.32",
"wasmtime-asm-macros",
"wasmtime-versioned-export-macros",
"windows-sys 0.52.0",
@@ -11343,9 +11307,9 @@ dependencies = [
[[package]]
name = "wasmtime-jit-icache-coherence"
-version = "18.0.2"
+version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33f4121cb29dda08139b2824a734dd095d83ce843f2d613a84eb580b9cfc17ac"
+checksum = "2796e4b4989db62899d2117e1e0258b839d088c044591b14e3a0396e7b3ae53a"
dependencies = [
"cfg-if",
"libc",
@@ -11354,9 +11318,9 @@ dependencies = [
[[package]]
name = "wasmtime-runtime"
-version = "18.0.2"
+version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e517f2b996bb3b0e34a82a2bce194f850d9bcfc25c08328ef5fb71b071066b8"
+checksum = "4bf2b7745df452a4f41b9aab21d3f7ba1347b12da2fdc5241e59306127884a68"
dependencies = [
"anyhow",
"cc",
@@ -11370,7 +11334,7 @@ dependencies = [
"memoffset 0.9.0",
"paste",
"psm",
- "rustix 0.38.30",
+ "rustix 0.38.32",
"sptr",
"wasm-encoder",
"wasmtime-asm-macros",
@@ -11381,11 +11345,17 @@ dependencies = [
"windows-sys 0.52.0",
]
+[[package]]
+name = "wasmtime-slab"
+version = "19.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83448ef600ad95977019ebaea84a5516fdbc9561d0a8e26b1e099351f993b527"
+
[[package]]
name = "wasmtime-types"
-version = "18.0.2"
+version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54a327d7a0ef57bd52a507d28b4561a74126c7a8535a2fc6f2025716bc6a52e8"
+checksum = "cf6fe7ed3fd18ed4b1e4465fe5c8674acc9f03523fca5b1b9f975b2560cd741b"
dependencies = [
"cranelift-entity",
"serde",
@@ -11396,9 +11366,9 @@ dependencies = [
[[package]]
name = "wasmtime-versioned-export-macros"
-version = "18.0.2"
+version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ef32eea9fc7035a55159a679d1e89b43ece5ae45d24eed4808e6a92c99a0da4"
+checksum = "6d6d967f01032da7d4c6303da32f6a00d5efe1bac124b156e7342d8ace6ffdfc"
dependencies = [
"proc-macro2",
"quote",
@@ -11407,9 +11377,9 @@ dependencies = [
[[package]]
name = "wasmtime-wasi"
-version = "18.0.2"
+version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d04d2fb2257245aa05ff799ded40520ae4d8cd31b0d14972afac89061f12fe12"
+checksum = "371d828b6849ea06d598ae7dd1c316e8dd9e99b76f77d93d5886cb25c7f8e188"
dependencies = [
"anyhow",
"async-trait",
@@ -11424,15 +11394,13 @@ dependencies = [
"futures 0.3.28",
"io-extras",
"io-lifetimes 2.0.3",
- "log",
"once_cell",
- "rustix 0.38.30",
+ "rustix 0.38.32",
"system-interface",
"thiserror",
"tokio",
"tracing",
"url",
- "wasi-common",
"wasmtime",
"wiggle",
"windows-sys 0.52.0",
@@ -11440,9 +11408,9 @@ dependencies = [
[[package]]
name = "wasmtime-winch"
-version = "18.0.2"
+version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db3378c0e808a744b5d4df2a9a9d2746a53b151811926731f04fc401707f7d54"
+checksum = "eb8b3fcbc455105760e4a2aa8ee3f39b8357183a62201383b3f72d4836ca2be8"
dependencies = [
"anyhow",
"cranelift-codegen",
@@ -11457,21 +11425,21 @@ dependencies = [
[[package]]
name = "wasmtime-wit-bindgen"
-version = "18.0.2"
+version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca677c36869e45602617b25a9968ec0d895ad9a0aee3756d9dee1ddd89456f91"
+checksum = "96326c9800fb6c099f50d1bd2126d636fc2f96950e1675acf358c0f52516cd38"
dependencies = [
"anyhow",
"heck 0.4.1",
"indexmap 2.0.0",
- "wit-parser 0.13.2",
+ "wit-parser",
]
[[package]]
name = "wasmtime-wmemcheck"
-version = "18.0.2"
+version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f4cbfb052d66f03603a9b77f18171ea245c7805714caad370a549a6344bf86b"
+checksum = "36bd91a4dc55af0bf55e9e2ab0ea13724cfb5c5a1acdf8873039769208f59490"
[[package]]
name = "wast"
@@ -11490,7 +11458,7 @@ checksum = "9d50fa61ce90d76474c87f5fc002828d81b32677340112b4ef08079a9d459a40"
dependencies = [
"cc",
"downcast-rs",
- "rustix 0.38.30",
+ "rustix 0.38.32",
"scoped-tls",
"smallvec",
"wayland-sys",
@@ -11503,7 +11471,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82fb96ee935c2cea6668ccb470fb7771f6215d1691746c2d896b447a00ad3f1f"
dependencies = [
"bitflags 2.4.2",
- "rustix 0.38.30",
+ "rustix 0.38.32",
"wayland-backend",
"wayland-scanner",
]
@@ -11525,7 +11493,7 @@ version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71ce5fa868dd13d11a0d04c5e2e65726d0897be8de247c0c5a65886e283231ba"
dependencies = [
- "rustix 0.38.30",
+ "rustix 0.38.32",
"wayland-client",
"xcursor",
]
@@ -11636,7 +11604,7 @@ dependencies = [
"either",
"home",
"once_cell",
- "rustix 0.38.30",
+ "rustix 0.38.32",
]
[[package]]
@@ -11648,7 +11616,7 @@ dependencies = [
"either",
"home",
"once_cell",
- "rustix 0.38.30",
+ "rustix 0.38.32",
"windows-sys 0.52.0",
]
@@ -11660,9 +11628,9 @@ checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50"
[[package]]
name = "wiggle"
-version = "18.0.2"
+version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b69812e493f8a43d8551abfaaf9539e1aff0cf56a58cdd276845fc4af035d0cd"
+checksum = "ae1136a209614ace00b0c11f04dc7cf42540773be3b22eff6ad165110aba29c1"
dependencies = [
"anyhow",
"async-trait",
@@ -11675,9 +11643,9 @@ dependencies = [
[[package]]
name = "wiggle-generate"
-version = "18.0.2"
+version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0446357a5a7af0172848b6eca7b2aa1ab7d90065cd2ab02b633a322e1a52f636"
+checksum = "4c2bd99ce26046f4246d720a4198f6a8fc95bc5da82ae4ef62263e24641c3076"
dependencies = [
"anyhow",
"heck 0.4.1",
@@ -11690,9 +11658,9 @@ dependencies = [
[[package]]
name = "wiggle-macro"
-version = "18.0.2"
+version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9498ef53a12cf25dc6de9baef6ccd8b58d159202c412a19f4d72b218393086c5"
+checksum = "512d816dbcd0113103b2eb2402ec9018e7f0755202a5b3e67db726f229d8dcae"
dependencies = [
"proc-macro2",
"quote",
@@ -11733,9 +11701,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "winch-codegen"
-version = "0.16.2"
+version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8197ed4a2ebf612f0624ddda10de71f8cd2d3a4ecf8ffac0586a264599708d63"
+checksum = "d285c833af9453c037cd220765f86c5c9961e8906a815829107c8801d535b8e4"
dependencies = [
"anyhow",
"cranelift-codegen",
@@ -12094,42 +12062,50 @@ dependencies = [
[[package]]
name = "wit-bindgen"
-version = "0.18.0"
+version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5408d742fcdf418b766f23b2393f0f4d9b10b72b7cd96d9525626943593e8cc0"
+checksum = "288f992ea30e6b5c531b52cdd5f3be81c148554b09ea416f058d16556ba92c27"
dependencies = [
"bitflags 2.4.2",
+ "wit-bindgen-rt",
"wit-bindgen-rust-macro",
]
[[package]]
name = "wit-bindgen-core"
-version = "0.18.0"
+version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7146725463d08ccf9c6c5357a7a6c1fff96185d95d6e84e7c75c92e5b1273c93"
+checksum = "e85e72719ffbccf279359ad071497e47eb0675fe22106dea4ed2d8a7fcb60ba4"
dependencies = [
"anyhow",
- "wit-parser 0.14.0",
+ "wit-parser",
]
+[[package]]
+name = "wit-bindgen-rt"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcb8738270f32a2d6739973cbbb7c1b6dd8959ce515578a6e19165853272ee64"
+
[[package]]
name = "wit-bindgen-rust"
-version = "0.18.0"
+version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb5fefcf93ff2ea03c8fe9b9db2caee3096103c0e3cd62ed54f6f9493aa6b405"
+checksum = "d8a39a15d1ae2077688213611209849cad40e9e5cccf6e61951a425850677ff3"
dependencies = [
"anyhow",
"heck 0.4.1",
+ "indexmap 2.0.0",
"wasm-metadata",
"wit-bindgen-core",
- "wit-component 0.21.0",
+ "wit-component",
]
[[package]]
name = "wit-bindgen-rust-macro"
-version = "0.18.1"
+version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce4059a1adc671e4457f457cb638ed2f766a1a462bb7daa3b638c6fb1fda156e"
+checksum = "d376d3ae5850526dfd00d937faea0d81a06fa18f7ac1e26f386d760f241a8f4b"
dependencies = [
"anyhow",
"proc-macro2",
@@ -12141,28 +12117,9 @@ dependencies = [
[[package]]
name = "wit-component"
-version = "0.20.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4436190e87b4e539807bcdcf5b817e79d2e29e16bc5ddb6445413fe3d1f5716"
-dependencies = [
- "anyhow",
- "bitflags 2.4.2",
- "indexmap 2.0.0",
- "log",
- "serde",
- "serde_derive",
- "serde_json",
- "wasm-encoder",
- "wasm-metadata",
- "wasmparser",
- "wit-parser 0.13.2",
-]
-
-[[package]]
-name = "wit-component"
-version = "0.21.0"
+version = "0.201.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be60cd1b2ff7919305301d0c27528d4867bd793afe890ba3837743da9655d91b"
+checksum = "421c0c848a0660a8c22e2fd217929a0191f14476b68962afd2af89fd22e39825"
dependencies = [
"anyhow",
"bitflags 2.4.2",
@@ -12174,31 +12131,14 @@ dependencies = [
"wasm-encoder",
"wasm-metadata",
"wasmparser",
- "wit-parser 0.14.0",
+ "wit-parser",
]
[[package]]
name = "wit-parser"
-version = "0.13.2"
+version = "0.201.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "316b36a9f0005f5aa4b03c39bc3728d045df136f8c13a73b7db4510dec725e08"
-dependencies = [
- "anyhow",
- "id-arena",
- "indexmap 2.0.0",
- "log",
- "semver",
- "serde",
- "serde_derive",
- "serde_json",
- "unicode-xid",
-]
-
-[[package]]
-name = "wit-parser"
-version = "0.14.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ee4ad7310367bf272507c0c8e0c74a80b4ed586b833f7c7ca0b7588f686f11a"
+checksum = "196d3ecfc4b759a8573bf86a9b3f8996b304b3732e4c7de81655f875f6efdca6"
dependencies = [
"anyhow",
"id-arena",
@@ -1,3 +1,4 @@
+
[workspace]
members = [
"crates/activity_indicator",
@@ -97,6 +98,7 @@ members = [
"extensions/gleam",
"extensions/uiua",
+ "extensions/svelte",
"tooling/xtask",
]
@@ -210,7 +212,7 @@ bitflags = "2.4.2"
blade-graphics = { git = "https://github.com/kvark/blade", rev = "61cbd6b2c224791d52b150fe535cee665cc91bb2" }
blade-macros = { git = "https://github.com/kvark/blade", rev = "61cbd6b2c224791d52b150fe535cee665cc91bb2" }
blade-rwh = { package = "raw-window-handle", version = "0.5" }
-cap-std = "2.0"
+cap-std = "3.0"
chrono = { version = "0.4", features = ["serde"] }
clap = { version = "4.4", features = ["derive"] }
clickhouse = { version = "0.11.6" }
@@ -293,7 +295,6 @@ tree-sitter-elixir = { git = "https://github.com/elixir-lang/tree-sitter-elixir"
tree-sitter-elm = { git = "https://github.com/elm-tooling/tree-sitter-elm", rev = "692c50c0b961364c40299e73c1306aecb5d20f40" }
tree-sitter-embedded-template = "0.20.0"
tree-sitter-erlang = "0.4.0"
-tree-sitter-gleam = { git = "https://github.com/gleam-lang/tree-sitter-gleam", rev = "58b7cac8fc14c92b0677c542610d8738c373fa81" }
tree-sitter-glsl = { git = "https://github.com/theHamsta/tree-sitter-glsl", rev = "2a56fb7bc8bb03a1892b4741279dd0a8758b7fb3" }
tree-sitter-go = { git = "https://github.com/tree-sitter/tree-sitter-go", rev = "aeb2f33b366fd78d5789ff104956ce23508b85db" }
tree-sitter-gomod = { git = "https://github.com/camdencheek/tree-sitter-go-mod" }
@@ -320,7 +321,6 @@ tree-sitter-regex = "0.20.0"
tree-sitter-ruby = "0.20.0"
tree-sitter-rust = "0.20.3"
tree-sitter-scheme = { git = "https://github.com/6cdh/tree-sitter-scheme", rev = "af0fd1fa452cb2562dc7b5c8a8c55551c39273b9" }
-tree-sitter-svelte = { git = "https://github.com/Himujjal/tree-sitter-svelte", rev = "bd60db7d3d06f89b6ec3b287c9a6e9190b5564bd" }
tree-sitter-toml = { git = "https://github.com/tree-sitter/tree-sitter-toml", rev = "342d9be207c2dba869b9967124c679b5e6fd0ebe" }
tree-sitter-typescript = { git = "https://github.com/tree-sitter/tree-sitter-typescript", rev = "5d20856f34315b068c41edaee2ac8a100081d259" }
tree-sitter-vue = { git = "https://github.com/zed-industries/tree-sitter-vue", rev = "6608d9d60c386f19d80af7d8132322fa11199c42" }
@@ -330,18 +330,18 @@ unindent = "0.1.7"
unicase = "2.6"
url = "2.2"
uuid = { version = "1.1.2", features = ["v4"] }
-wasmparser = "0.121"
-wasm-encoder = "0.41"
-wasmtime = { version = "18.0", default-features = false, features = [
+wasmparser = "0.201"
+wasm-encoder = "0.201"
+wasmtime = { version = "19.0.0", default-features = false, features = [
"async",
"demangle",
"runtime",
"cranelift",
"component-model",
] }
-wasmtime-wasi = "18.0"
+wasmtime-wasi = "19.0.0"
which = "6.0.0"
-wit-component = "0.20"
+wit-component = "0.201"
sys-locale = "0.3.1"
[workspace.dependencies.windows]
@@ -375,7 +375,7 @@ features = [
]
[patch.crates-io]
-tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "4294e59279205f503eb14348dd5128bd5910c8fb" }
+tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "05079ae3d1bc44bedc4594eef925b36ba5e317a2" }
# Workaround for a broken nightly build of gpui: See #7644 and revisit once 0.5.3 is released.
pathfinder_simd = { git = "https://github.com/servo/pathfinder.git", rev = "30419d07660dc11a21e42ef4a7fa329600cff152" }
@@ -389,6 +389,7 @@ cranelift-codegen = { opt-level = 3 }
rustybuzz = { opt-level = 3 }
ttf-parser = { opt-level = 3 }
wasmtime-cranelift = { opt-level = 3 }
+wasmtime = { opt-level = 3 }
[profile.release]
debug = "limited"
@@ -205,7 +205,7 @@ impl ActivityIndicator {
}
LanguageServerBinaryStatus::Downloading => downloading.push(status.name.0.as_ref()),
LanguageServerBinaryStatus::Failed { .. } => failed.push(status.name.0.as_ref()),
- LanguageServerBinaryStatus::Downloaded | LanguageServerBinaryStatus::Cached => {}
+ LanguageServerBinaryStatus::None => {}
}
}
@@ -17,7 +17,7 @@ use rpc::{
};
use settings::Settings;
use std::{mem, sync::Arc, time::Duration};
-use util::{async_maybe, maybe, ResultExt};
+use util::{maybe, ResultExt};
pub const RECONNECT_TIMEOUT: Duration = Duration::from_secs(30);
@@ -227,7 +227,7 @@ impl ChannelStore {
_watch_connection_status: watch_connection_status,
disconnect_channel_buffers_task: None,
_update_channels: cx.spawn(|this, mut cx| async move {
- async_maybe!({
+ maybe!(async move {
while let Some(update_channels) = update_channels_rx.next().await {
if let Some(this) = this.upgrade() {
let update_task = this.update(&mut cx, |this, cx| {
@@ -1228,25 +1228,21 @@ async fn create_room(
) -> Result<()> {
let live_kit_room = nanoid::nanoid!(30);
- let live_kit_connection_info = {
- let live_kit_room = live_kit_room.clone();
+ let live_kit_connection_info = util::maybe!(async {
let live_kit = session.live_kit_client.as_ref();
+ let live_kit = live_kit?;
let user_id = session.user_id().to_string();
- util::async_maybe!({
- let live_kit = live_kit?;
+ let token = live_kit
+ .room_token(&live_kit_room, &user_id.to_string())
+ .trace_err()?;
- let token = live_kit
- .room_token(&live_kit_room, &user_id.to_string())
- .trace_err()?;
-
- Some(proto::LiveKitConnectionInfo {
- server_url: live_kit.url().into(),
- token,
- can_publish: true,
- })
+ Some(proto::LiveKitConnectionInfo {
+ server_url: live_kit.url().into(),
+ token,
+ can_publish: true,
})
- }
+ })
.await;
let room = session
@@ -29,8 +29,7 @@ use std::{
sync::Arc,
};
use util::{
- async_maybe, fs::remove_matching, github::latest_github_release, http::HttpClient, paths,
- ResultExt,
+ fs::remove_matching, github::latest_github_release, http::HttpClient, maybe, paths, ResultExt,
};
actions!(
@@ -1006,7 +1005,7 @@ async fn get_copilot_lsp(http: Arc<dyn HttpClient>) -> anyhow::Result<PathBuf> {
e @ Err(..) => {
e.log_err();
// Fetch a cached binary, if it exists
- async_maybe!({
+ maybe!(async {
let mut last_version_dir = None;
let mut entries = fs::read_dir(paths::COPILOT_DIR.as_path()).await?;
while let Some(entry) = entries.next().await {
@@ -20,7 +20,7 @@ use sqlez_macros::sql;
use std::future::Future;
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicBool, Ordering};
-use util::{async_maybe, ResultExt};
+use util::{maybe, ResultExt};
const CONNECTION_INITIALIZE_QUERY: &str = sql!(
PRAGMA foreign_keys=TRUE;
@@ -57,7 +57,7 @@ pub async fn open_db<M: Migrator + 'static>(
let release_channel_name = release_channel.dev_name();
let main_db_dir = db_dir.join(Path::new(&format!("0-{}", release_channel_name)));
- let connection = async_maybe!({
+ let connection = maybe!(async {
smol::fs::create_dir_all(&main_db_dir)
.await
.context("Could not create db directory")
@@ -85,10 +85,7 @@ impl ExtensionBuilder {
let cargo_toml_path = extension_dir.join("Cargo.toml");
if extension_manifest.lib.kind == Some(ExtensionLibraryKind::Rust)
- || fs::metadata(&cargo_toml_path)
- .ok()
- .map(|metadata| metadata.is_file())
- .unwrap_or(false)
+ || fs::metadata(&cargo_toml_path).map_or(false, |stat| stat.is_file())
{
log::info!("compiling Rust extension {}", extension_dir.display());
self.compile_rust_extension(extension_dir, options)
@@ -11,7 +11,7 @@ use std::{
pin::Pin,
sync::Arc,
};
-use wasmtime_wasi::preview2::WasiView as _;
+use wasmtime_wasi::WasiView as _;
pub struct ExtensionLspAdapter {
pub(crate) extension: WasmExtension,
@@ -39,6 +39,7 @@ use theme::{ThemeRegistry, ThemeSettings};
use url::Url;
use util::{
http::{AsyncBody, HttpClient, HttpClientWithUrl},
+ maybe,
paths::EXTENSIONS_DIR,
ResultExt,
};
@@ -108,6 +109,7 @@ pub enum Event {
ExtensionsUpdated,
StartedReloading,
ExtensionInstalled(Arc<str>),
+ ExtensionFailedToLoad(Arc<str>),
}
impl EventEmitter<Event> for ExtensionStore {}
@@ -886,41 +888,38 @@ impl ExtensionStore {
continue;
};
- let mut path = root_dir.clone();
- path.extend([extension.manifest.id.as_ref(), "extension.wasm"]);
- let Some(mut wasm_file) = fs
- .open_sync(&path)
- .await
- .context("failed to open wasm file")
- .log_err()
- else {
- continue;
- };
+ let wasm_extension = maybe!(async {
+ let mut path = root_dir.clone();
+ path.extend([extension.manifest.clone().id.as_ref(), "extension.wasm"]);
+ let mut wasm_file = fs
+ .open_sync(&path)
+ .await
+ .context("failed to open wasm file")?;
+
+ let mut wasm_bytes = Vec::new();
+ wasm_file
+ .read_to_end(&mut wasm_bytes)
+ .context("failed to read wasm")?;
+
+ wasm_host
+ .load_extension(
+ wasm_bytes,
+ extension.manifest.clone().clone(),
+ cx.background_executor().clone(),
+ )
+ .await
+ .context("failed to load wasm extension")
+ })
+ .await;
- let mut wasm_bytes = Vec::new();
- if wasm_file
- .read_to_end(&mut wasm_bytes)
- .context("failed to read wasm")
- .log_err()
- .is_none()
- {
- continue;
+ if let Some(wasm_extension) = wasm_extension.log_err() {
+ wasm_extensions.push((extension.manifest.clone(), wasm_extension));
+ } else {
+ this.update(&mut cx, |_, cx| {
+ cx.emit(Event::ExtensionFailedToLoad(extension.manifest.id.clone()))
+ })
+ .ok();
}
-
- let Some(wasm_extension) = wasm_host
- .load_extension(
- wasm_bytes,
- extension.manifest.clone(),
- cx.background_executor().clone(),
- )
- .await
- .context("failed to load wasm extension")
- .log_err()
- else {
- continue;
- };
-
- wasm_extensions.push((extension.manifest.clone(), wasm_extension));
}
this.update(&mut cx, |this, cx| {
@@ -1,6 +1,7 @@
use crate::{
- ExtensionIndex, ExtensionIndexEntry, ExtensionIndexLanguageEntry, ExtensionIndexThemeEntry,
- ExtensionManifest, ExtensionStore, GrammarManifestEntry, RELOAD_DEBOUNCE_DURATION,
+ Event, ExtensionIndex, ExtensionIndexEntry, ExtensionIndexLanguageEntry,
+ ExtensionIndexThemeEntry, ExtensionManifest, ExtensionStore, GrammarManifestEntry,
+ RELOAD_DEBOUNCE_DURATION,
};
use async_compression::futures::bufread::GzipEncoder;
use collections::BTreeMap;
@@ -558,6 +559,15 @@ async fn test_extension_store_with_gleam_extension(cx: &mut TestAppContext) {
}
});
+ extension_store.update(cx, |_, cx| {
+ cx.subscribe(&extension_store, |_, _, event, _| {
+ if matches!(event, Event::ExtensionFailedToLoad(_)) {
+ panic!("extension failed to load");
+ }
+ })
+ .detach();
+ });
+
extension_store
.update(cx, |store, cx| {
store.install_dev_extension(gleam_extension_dir.clone(), cx)
@@ -602,7 +612,7 @@ async fn test_extension_store_with_gleam_extension(cx: &mut TestAppContext) {
),
(
LanguageServerName("gleam".into()),
- LanguageServerBinaryStatus::Downloaded
+ LanguageServerBinaryStatus::None
)
]
);
@@ -1,8 +1,7 @@
+pub(crate) mod wit;
+
use crate::ExtensionManifest;
use anyhow::{anyhow, bail, Context as _, Result};
-use async_compression::futures::bufread::GzipDecoder;
-use async_tar::Archive;
-use async_trait::async_trait;
use fs::{normalize_path, Fs};
use futures::{
channel::{
@@ -10,42 +9,28 @@ use futures::{
oneshot,
},
future::BoxFuture,
- io::BufReader,
Future, FutureExt, StreamExt as _,
};
use gpui::BackgroundExecutor;
-use language::{LanguageRegistry, LanguageServerBinaryStatus, LspAdapterDelegate};
+use language::LanguageRegistry;
use node_runtime::NodeRuntime;
use std::{
- env,
path::{Path, PathBuf},
sync::{Arc, OnceLock},
};
use util::{http::HttpClient, SemanticVersion};
use wasmtime::{
- component::{Component, Linker, Resource, ResourceTable},
+ component::{Component, ResourceTable},
Engine, Store,
};
-use wasmtime_wasi::preview2::{self as wasi, WasiCtx};
-
-pub mod wit {
- wasmtime::component::bindgen!({
- async: true,
- path: "../extension_api/wit",
- with: {
- "worktree": super::ExtensionWorktree,
- },
- });
-}
-
-pub type ExtensionWorktree = Arc<dyn LspAdapterDelegate>;
+use wasmtime_wasi as wasi;
+use wit::Extension;
pub(crate) struct WasmHost {
engine: Engine,
- linker: Arc<wasmtime::component::Linker<WasmState>>,
http_client: Arc<dyn HttpClient>,
node_runtime: Arc<dyn NodeRuntime>,
- language_registry: Arc<LanguageRegistry>,
+ pub(crate) language_registry: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
pub(crate) work_dir: PathBuf,
}
@@ -60,17 +45,27 @@ pub struct WasmExtension {
pub(crate) struct WasmState {
manifest: Arc<ExtensionManifest>,
- table: ResourceTable,
+ pub(crate) table: ResourceTable,
ctx: wasi::WasiCtx,
- host: Arc<WasmHost>,
+ pub(crate) host: Arc<WasmHost>,
}
type ExtensionCall = Box<
- dyn Send
- + for<'a> FnOnce(&'a mut wit::Extension, &'a mut Store<WasmState>) -> BoxFuture<'a, ()>,
+ dyn Send + for<'a> FnOnce(&'a mut Extension, &'a mut Store<WasmState>) -> BoxFuture<'a, ()>,
>;
-static WASM_ENGINE: OnceLock<wasmtime::Engine> = OnceLock::new();
+fn wasm_engine() -> wasmtime::Engine {
+ static WASM_ENGINE: OnceLock<wasmtime::Engine> = OnceLock::new();
+
+ WASM_ENGINE
+ .get_or_init(|| {
+ let mut config = wasmtime::Config::new();
+ config.wasm_component_model(true);
+ config.async_support(true);
+ wasmtime::Engine::new(&config).unwrap()
+ })
+ .clone()
+}
impl WasmHost {
pub fn new(
@@ -80,20 +75,8 @@ impl WasmHost {
language_registry: Arc<LanguageRegistry>,
work_dir: PathBuf,
) -> Arc<Self> {
- let engine = WASM_ENGINE
- .get_or_init(|| {
- let mut config = wasmtime::Config::new();
- config.wasm_component_model(true);
- config.async_support(true);
- wasmtime::Engine::new(&config).unwrap()
- })
- .clone();
- let mut linker = Linker::new(&engine);
- wasi::command::add_to_linker(&mut linker).unwrap();
- wit::Extension::add_to_linker(&mut linker, wasi_view).unwrap();
Arc::new(Self {
- engine,
- linker: Arc::new(linker),
+ engine: wasm_engine(),
fs,
work_dir,
http_client,
@@ -144,9 +127,8 @@ impl WasmHost {
);
let (mut extension, instance) =
- wit::Extension::instantiate_async(&mut store, &component, &this.linker)
- .await
- .context("failed to instantiate wasm extension")?;
+ Extension::instantiate_async(&mut store, zed_api_version, &component).await?;
+
extension
.call_init_extension(&mut store)
.await
@@ -170,7 +152,7 @@ impl WasmHost {
}
}
- async fn build_wasi_ctx(&self, manifest: &Arc<ExtensionManifest>) -> Result<WasiCtx> {
+ async fn build_wasi_ctx(&self, manifest: &Arc<ExtensionManifest>) -> Result<wasi::WasiCtx> {
use cap_std::{ambient_authority, fs::Dir};
let extension_work_dir = self.work_dir.join(manifest.id.as_ref());
@@ -232,7 +214,7 @@ impl WasmExtension {
T: 'static + Send,
Fn: 'static
+ Send
- + for<'a> FnOnce(&'a mut wit::Extension, &'a mut Store<WasmState>) -> BoxFuture<'a, T>,
+ + for<'a> FnOnce(&'a mut Extension, &'a mut Store<WasmState>) -> BoxFuture<'a, T>,
{
let (return_tx, return_rx) = oneshot::channel();
self.tx
@@ -249,279 +231,10 @@ impl WasmExtension {
}
}
-#[async_trait]
-impl wit::HostWorktree for WasmState {
- async fn read_text_file(
- &mut self,
- delegate: Resource<Arc<dyn LspAdapterDelegate>>,
- path: String,
- ) -> wasmtime::Result<Result<String, String>> {
- let delegate = self.table.get(&delegate)?;
- Ok(delegate
- .read_text_file(path.into())
- .await
- .map_err(|error| error.to_string()))
- }
-
- async fn shell_env(
- &mut self,
- delegate: Resource<Arc<dyn LspAdapterDelegate>>,
- ) -> wasmtime::Result<wit::EnvVars> {
- let delegate = self.table.get(&delegate)?;
- Ok(delegate.shell_env().await.into_iter().collect())
- }
-
- async fn which(
- &mut self,
- delegate: Resource<Arc<dyn LspAdapterDelegate>>,
- binary_name: String,
- ) -> wasmtime::Result<Option<String>> {
- let delegate = self.table.get(&delegate)?;
- Ok(delegate
- .which(binary_name.as_ref())
- .await
- .map(|path| path.to_string_lossy().to_string()))
- }
-
- fn drop(&mut self, _worktree: Resource<wit::Worktree>) -> Result<()> {
- // we only ever hand out borrows of worktrees
- Ok(())
- }
-}
-
-#[async_trait]
-impl wit::ExtensionImports for WasmState {
- async fn npm_package_latest_version(
- &mut self,
- package_name: String,
- ) -> wasmtime::Result<Result<String, String>> {
- async fn inner(this: &mut WasmState, package_name: String) -> anyhow::Result<String> {
- this.host
- .node_runtime
- .npm_package_latest_version(&package_name)
- .await
- }
-
- Ok(inner(self, package_name)
- .await
- .map_err(|err| err.to_string()))
+impl WasmState {
+ fn work_dir(&self) -> PathBuf {
+ self.host.work_dir.join(self.manifest.id.as_ref())
}
-
- async fn npm_package_installed_version(
- &mut self,
- package_name: String,
- ) -> wasmtime::Result<Result<Option<String>, String>> {
- async fn inner(
- this: &mut WasmState,
- package_name: String,
- ) -> anyhow::Result<Option<String>> {
- this.host
- .node_runtime
- .npm_package_installed_version(&this.host.work_dir, &package_name)
- .await
- }
-
- Ok(inner(self, package_name)
- .await
- .map_err(|err| err.to_string()))
- }
-
- async fn npm_install_package(
- &mut self,
- package_name: String,
- version: String,
- ) -> wasmtime::Result<Result<(), String>> {
- async fn inner(
- this: &mut WasmState,
- package_name: String,
- version: String,
- ) -> anyhow::Result<()> {
- this.host
- .node_runtime
- .npm_install_packages(&this.host.work_dir, &[(&package_name, &version)])
- .await
- }
-
- Ok(inner(self, package_name, version)
- .await
- .map_err(|err| err.to_string()))
- }
-
- async fn latest_github_release(
- &mut self,
- repo: String,
- options: wit::GithubReleaseOptions,
- ) -> wasmtime::Result<Result<wit::GithubRelease, String>> {
- async fn inner(
- this: &mut WasmState,
- repo: String,
- options: wit::GithubReleaseOptions,
- ) -> anyhow::Result<wit::GithubRelease> {
- let release = util::github::latest_github_release(
- &repo,
- options.require_assets,
- options.pre_release,
- this.host.http_client.clone(),
- )
- .await?;
- Ok(wit::GithubRelease {
- version: release.tag_name,
- assets: release
- .assets
- .into_iter()
- .map(|asset| wit::GithubReleaseAsset {
- name: asset.name,
- download_url: asset.browser_download_url,
- })
- .collect(),
- })
- }
-
- Ok(inner(self, repo, options)
- .await
- .map_err(|err| err.to_string()))
- }
-
- async fn current_platform(&mut self) -> Result<(wit::Os, wit::Architecture)> {
- Ok((
- match env::consts::OS {
- "macos" => wit::Os::Mac,
- "linux" => wit::Os::Linux,
- "windows" => wit::Os::Windows,
- _ => panic!("unsupported os"),
- },
- match env::consts::ARCH {
- "aarch64" => wit::Architecture::Aarch64,
- "x86" => wit::Architecture::X86,
- "x86_64" => wit::Architecture::X8664,
- _ => panic!("unsupported architecture"),
- },
- ))
- }
-
- async fn set_language_server_installation_status(
- &mut self,
- server_name: String,
- status: wit::LanguageServerInstallationStatus,
- ) -> wasmtime::Result<()> {
- let status = match status {
- wit::LanguageServerInstallationStatus::CheckingForUpdate => {
- LanguageServerBinaryStatus::CheckingForUpdate
- }
- wit::LanguageServerInstallationStatus::Downloading => {
- LanguageServerBinaryStatus::Downloading
- }
- wit::LanguageServerInstallationStatus::Downloaded => {
- LanguageServerBinaryStatus::Downloaded
- }
- wit::LanguageServerInstallationStatus::Cached => LanguageServerBinaryStatus::Cached,
- wit::LanguageServerInstallationStatus::Failed(error) => {
- LanguageServerBinaryStatus::Failed { error }
- }
- };
-
- self.host
- .language_registry
- .update_lsp_status(language::LanguageServerName(server_name.into()), status);
- Ok(())
- }
-
- async fn download_file(
- &mut self,
- url: String,
- path: String,
- file_type: wit::DownloadedFileType,
- ) -> wasmtime::Result<Result<(), String>> {
- let path = PathBuf::from(path);
-
- async fn inner(
- this: &mut WasmState,
- url: String,
- path: PathBuf,
- file_type: wit::DownloadedFileType,
- ) -> anyhow::Result<()> {
- let extension_work_dir = this.host.work_dir.join(this.manifest.id.as_ref());
-
- this.host.fs.create_dir(&extension_work_dir).await?;
-
- let destination_path = this
- .host
- .writeable_path_from_extension(&this.manifest.id, &path)?;
-
- let mut response = this
- .host
- .http_client
- .get(&url, Default::default(), true)
- .await
- .map_err(|err| anyhow!("error downloading release: {}", err))?;
-
- if !response.status().is_success() {
- Err(anyhow!(
- "download failed with status {}",
- response.status().to_string()
- ))?;
- }
- let body = BufReader::new(response.body_mut());
-
- match file_type {
- wit::DownloadedFileType::Uncompressed => {
- futures::pin_mut!(body);
- this.host
- .fs
- .create_file_with(&destination_path, body)
- .await?;
- }
- wit::DownloadedFileType::Gzip => {
- let body = GzipDecoder::new(body);
- futures::pin_mut!(body);
- this.host
- .fs
- .create_file_with(&destination_path, body)
- .await?;
- }
- wit::DownloadedFileType::GzipTar => {
- let body = GzipDecoder::new(body);
- futures::pin_mut!(body);
- this.host
- .fs
- .extract_tar_file(&destination_path, Archive::new(body))
- .await?;
- }
- wit::DownloadedFileType::Zip => {
- let file_name = destination_path
- .file_name()
- .ok_or_else(|| anyhow!("invalid download path"))?
- .to_string_lossy();
- let zip_filename = format!("{file_name}.zip");
- let mut zip_path = destination_path.clone();
- zip_path.set_file_name(zip_filename);
-
- futures::pin_mut!(body);
- this.host.fs.create_file_with(&zip_path, body).await?;
-
- let unzip_status = std::process::Command::new("unzip")
- .current_dir(&extension_work_dir)
- .arg(&zip_path)
- .output()?
- .status;
- if !unzip_status.success() {
- Err(anyhow!("failed to unzip {} archive", path.display()))?;
- }
- }
- }
-
- Ok(())
- }
-
- Ok(inner(self, url, path, file_type)
- .await
- .map(|_| ())
- .map_err(|err| err.to_string()))
- }
-}
-
-fn wasi_view(state: &mut WasmState) -> &mut WasmState {
- state
}
impl wasi::WasiView for WasmState {
@@ -0,0 +1,103 @@
+mod v0_0_1;
+mod v0_0_4;
+
+use super::{wasm_engine, WasmState};
+use anyhow::{Context, Result};
+use language::LspAdapterDelegate;
+use std::sync::Arc;
+use util::SemanticVersion;
+use wasmtime::{
+ component::{Component, Instance, Linker, Resource},
+ Store,
+};
+
+use v0_0_4 as latest;
+
+pub use latest::{Command, LanguageServerConfig};
+
+pub fn new_linker(
+ f: impl Fn(&mut Linker<WasmState>, fn(&mut WasmState) -> &mut WasmState) -> Result<()>,
+) -> Linker<WasmState> {
+ let mut linker = Linker::new(&wasm_engine());
+ wasmtime_wasi::command::add_to_linker(&mut linker).unwrap();
+ f(&mut linker, wasi_view).unwrap();
+ linker
+}
+
+fn wasi_view(state: &mut WasmState) -> &mut WasmState {
+ state
+}
+
+pub enum Extension {
+ V004(v0_0_4::Extension),
+ V001(v0_0_1::Extension),
+}
+
+impl Extension {
+ pub async fn instantiate_async(
+ store: &mut Store<WasmState>,
+ version: SemanticVersion,
+ component: &Component,
+ ) -> Result<(Self, Instance)> {
+ if version < latest::VERSION {
+ let (extension, instance) =
+ v0_0_1::Extension::instantiate_async(store, &component, v0_0_1::linker())
+ .await
+ .context("failed to instantiate wasm extension")?;
+ Ok((Self::V001(extension), instance))
+ } else {
+ let (extension, instance) =
+ v0_0_4::Extension::instantiate_async(store, &component, v0_0_4::linker())
+ .await
+ .context("failed to instantiate wasm extension")?;
+ Ok((Self::V004(extension), instance))
+ }
+ }
+
+ pub async fn call_init_extension(&self, store: &mut Store<WasmState>) -> Result<()> {
+ match self {
+ Extension::V004(ext) => ext.call_init_extension(store).await,
+ Extension::V001(ext) => ext.call_init_extension(store).await,
+ }
+ }
+
+ pub async fn call_language_server_command(
+ &self,
+ store: &mut Store<WasmState>,
+ config: &LanguageServerConfig,
+ resource: Resource<Arc<dyn LspAdapterDelegate>>,
+ ) -> Result<Result<Command, String>> {
+ match self {
+ Extension::V004(ext) => {
+ ext.call_language_server_command(store, config, resource)
+ .await
+ }
+ Extension::V001(ext) => Ok(ext
+ .call_language_server_command(store, &config.clone().into(), resource)
+ .await?
+ .map(|command| command.into())),
+ }
+ }
+
+ pub async fn call_language_server_initialization_options(
+ &self,
+ store: &mut Store<WasmState>,
+ config: &LanguageServerConfig,
+ resource: Resource<Arc<dyn LspAdapterDelegate>>,
+ ) -> Result<Result<Option<String>, String>> {
+ match self {
+ Extension::V004(ext) => {
+ ext.call_language_server_initialization_options(store, config, resource)
+ .await
+ }
+ Extension::V001(ext) => {
+ ext.call_language_server_initialization_options(
+ store,
+ &config.clone().into(),
+ resource,
+ )
+ .await
+ }
+ }
+ }
+}
@@ -0,0 +1,210 @@
+use super::latest;
+use crate::wasm_host::WasmState;
+use anyhow::Result;
+use async_trait::async_trait;
+use language::{LanguageServerBinaryStatus, LspAdapterDelegate};
+use std::sync::{Arc, OnceLock};
+use wasmtime::component::{Linker, Resource};
+
+wasmtime::component::bindgen!({
+ async: true,
+ path: "../extension_api/wit/0.0.1",
+ with: {
+ "worktree": ExtensionWorktree,
+ },
+});
+
+pub type ExtensionWorktree = Arc<dyn LspAdapterDelegate>;
+
+pub fn linker() -> &'static Linker<WasmState> {
+ static LINKER: OnceLock<Linker<WasmState>> = OnceLock::new();
+ LINKER.get_or_init(|| super::new_linker(Extension::add_to_linker))
+}
+
+impl From<latest::Os> for Os {
+ fn from(value: latest::Os) -> Self {
+ match value {
+ latest::Os::Mac => Os::Mac,
+ latest::Os::Linux => Os::Linux,
+ latest::Os::Windows => Os::Windows,
+ }
+ }
+}
+
+impl From<latest::Architecture> for Architecture {
+ fn from(value: latest::Architecture) -> Self {
+ match value {
+ latest::Architecture::Aarch64 => Self::Aarch64,
+ latest::Architecture::X86 => Self::X86,
+ latest::Architecture::X8664 => Self::X8664,
+ }
+ }
+}
+
+impl From<latest::GithubRelease> for GithubRelease {
+ fn from(value: latest::GithubRelease) -> Self {
+ Self {
+ version: value.version,
+ assets: value.assets.into_iter().map(|asset| asset.into()).collect(),
+ }
+ }
+}
+
+impl From<latest::GithubReleaseAsset> for GithubReleaseAsset {
+ fn from(value: latest::GithubReleaseAsset) -> Self {
+ Self {
+ name: value.name,
+ download_url: value.download_url,
+ }
+ }
+}
+
+impl From<GithubReleaseOptions> for latest::GithubReleaseOptions {
+ fn from(value: GithubReleaseOptions) -> Self {
+ Self {
+ require_assets: value.require_assets,
+ pre_release: value.pre_release,
+ }
+ }
+}
+
+impl From<DownloadedFileType> for latest::DownloadedFileType {
+ fn from(value: DownloadedFileType) -> Self {
+ match value {
+ DownloadedFileType::Gzip => latest::DownloadedFileType::Gzip,
+ DownloadedFileType::GzipTar => latest::DownloadedFileType::GzipTar,
+ DownloadedFileType::Zip => latest::DownloadedFileType::Zip,
+ DownloadedFileType::Uncompressed => latest::DownloadedFileType::Uncompressed,
+ }
+ }
+}
+
+impl From<latest::LanguageServerConfig> for LanguageServerConfig {
+ fn from(value: latest::LanguageServerConfig) -> Self {
+ Self {
+ name: value.name,
+ language_name: value.language_name,
+ }
+ }
+}
+
+impl From<Command> for latest::Command {
+ fn from(value: Command) -> Self {
+ Self {
+ command: value.command,
+ args: value.args,
+ env: value.env,
+ }
+ }
+}
+
+#[async_trait]
+impl HostWorktree for WasmState {
+ async fn read_text_file(
+ &mut self,
+ delegate: Resource<Arc<dyn LspAdapterDelegate>>,
+ path: String,
+ ) -> wasmtime::Result<Result<String, String>> {
+ latest::HostWorktree::read_text_file(self, delegate, path).await
+ }
+
+ async fn shell_env(
+ &mut self,
+ delegate: Resource<Arc<dyn LspAdapterDelegate>>,
+ ) -> wasmtime::Result<EnvVars> {
+ latest::HostWorktree::shell_env(self, delegate).await
+ }
+
+ async fn which(
+ &mut self,
+ delegate: Resource<Arc<dyn LspAdapterDelegate>>,
+ binary_name: String,
+ ) -> wasmtime::Result<Option<String>> {
+ latest::HostWorktree::which(self, delegate, binary_name).await
+ }
+
+ fn drop(&mut self, _worktree: Resource<Worktree>) -> Result<()> {
+ Ok(())
+ }
+}
+
+#[async_trait]
+impl ExtensionImports for WasmState {
+ async fn node_binary_path(&mut self) -> wasmtime::Result<Result<String, String>> {
+ latest::ExtensionImports::node_binary_path(self).await
+ }
+
+ async fn npm_package_latest_version(
+ &mut self,
+ package_name: String,
+ ) -> wasmtime::Result<Result<String, String>> {
+ latest::ExtensionImports::npm_package_latest_version(self, package_name).await
+ }
+
+ async fn npm_package_installed_version(
+ &mut self,
+ package_name: String,
+ ) -> wasmtime::Result<Result<Option<String>, String>> {
+ latest::ExtensionImports::npm_package_installed_version(self, package_name).await
+ }
+
+ async fn npm_install_package(
+ &mut self,
+ package_name: String,
+ version: String,
+ ) -> wasmtime::Result<Result<(), String>> {
+ latest::ExtensionImports::npm_install_package(self, package_name, version).await
+ }
+
+ async fn latest_github_release(
+ &mut self,
+ repo: String,
+ options: GithubReleaseOptions,
+ ) -> wasmtime::Result<Result<GithubRelease, String>> {
+ Ok(
+ latest::ExtensionImports::latest_github_release(self, repo, options.into())
+ .await?
+ .map(|github| github.into()),
+ )
+ }
+
+ async fn current_platform(&mut self) -> Result<(Os, Architecture)> {
+ latest::ExtensionImports::current_platform(self)
+ .await
+ .map(|(os, arch)| (os.into(), arch.into()))
+ }
+
+ async fn set_language_server_installation_status(
+ &mut self,
+ server_name: String,
+ status: LanguageServerInstallationStatus,
+ ) -> wasmtime::Result<()> {
+ let status = match status {
+ LanguageServerInstallationStatus::CheckingForUpdate => {
+ LanguageServerBinaryStatus::CheckingForUpdate
+ }
+ LanguageServerInstallationStatus::Downloading => {
+ LanguageServerBinaryStatus::Downloading
+ }
+ LanguageServerInstallationStatus::Cached
+ | LanguageServerInstallationStatus::Downloaded => LanguageServerBinaryStatus::None,
+ LanguageServerInstallationStatus::Failed(error) => {
+ LanguageServerBinaryStatus::Failed { error }
+ }
+ };
+
+ self.host
+ .language_registry
+ .update_lsp_status(language::LanguageServerName(server_name.into()), status);
+ Ok(())
+ }
+
+ async fn download_file(
+ &mut self,
+ url: String,
+ path: String,
+ file_type: DownloadedFileType,
+ ) -> wasmtime::Result<Result<(), String>> {
+ latest::ExtensionImports::download_file(self, url, path, file_type.into()).await
+ }
+}
@@ -0,0 +1,284 @@
+use crate::wasm_host::WasmState;
+use anyhow::{anyhow, Result};
+use async_compression::futures::bufread::GzipDecoder;
+use async_tar::Archive;
+use async_trait::async_trait;
+use futures::io::BufReader;
+use language::{LanguageServerBinaryStatus, LspAdapterDelegate};
+use std::{
+ env,
+ path::PathBuf,
+ sync::{Arc, OnceLock},
+};
+use util::{maybe, SemanticVersion};
+use wasmtime::component::{Linker, Resource};
+
+pub const VERSION: SemanticVersion = SemanticVersion {
+ major: 0,
+ minor: 0,
+ patch: 4,
+};
+
+wasmtime::component::bindgen!({
+ async: true,
+ path: "../extension_api/wit/0.0.4",
+ with: {
+ "worktree": ExtensionWorktree,
+ },
+});
+
+pub type ExtensionWorktree = Arc<dyn LspAdapterDelegate>;
+
+pub fn linker() -> &'static Linker<WasmState> {
+ static LINKER: OnceLock<Linker<WasmState>> = OnceLock::new();
+ LINKER.get_or_init(|| super::new_linker(Extension::add_to_linker))
+}
+
+#[async_trait]
+impl HostWorktree for WasmState {
+ async fn read_text_file(
+ &mut self,
+ delegate: Resource<Arc<dyn LspAdapterDelegate>>,
+ path: String,
+ ) -> wasmtime::Result<Result<String, String>> {
+ let delegate = self.table.get(&delegate)?;
+ Ok(delegate
+ .read_text_file(path.into())
+ .await
+ .map_err(|error| error.to_string()))
+ }
+
+ async fn shell_env(
+ &mut self,
+ delegate: Resource<Arc<dyn LspAdapterDelegate>>,
+ ) -> wasmtime::Result<EnvVars> {
+ let delegate = self.table.get(&delegate)?;
+ Ok(delegate.shell_env().await.into_iter().collect())
+ }
+
+ async fn which(
+ &mut self,
+ delegate: Resource<Arc<dyn LspAdapterDelegate>>,
+ binary_name: String,
+ ) -> wasmtime::Result<Option<String>> {
+ let delegate = self.table.get(&delegate)?;
+ Ok(delegate
+ .which(binary_name.as_ref())
+ .await
+ .map(|path| path.to_string_lossy().to_string()))
+ }
+
+ fn drop(&mut self, _worktree: Resource<Worktree>) -> Result<()> {
+ // we only ever hand out borrows of worktrees
+ Ok(())
+ }
+}
+
+#[async_trait]
+impl ExtensionImports for WasmState {
+ async fn node_binary_path(&mut self) -> wasmtime::Result<Result<String, String>> {
+ convert_result(
+ self.host
+ .node_runtime
+ .binary_path()
+ .await
+ .map(|path| path.to_string_lossy().to_string()),
+ )
+ }
+
+ async fn npm_package_latest_version(
+ &mut self,
+ package_name: String,
+ ) -> wasmtime::Result<Result<String, String>> {
+ convert_result(
+ self.host
+ .node_runtime
+ .npm_package_latest_version(&package_name)
+ .await,
+ )
+ }
+
+ async fn npm_package_installed_version(
+ &mut self,
+ package_name: String,
+ ) -> wasmtime::Result<Result<Option<String>, String>> {
+ convert_result(
+ self.host
+ .node_runtime
+ .npm_package_installed_version(&self.work_dir(), &package_name)
+ .await,
+ )
+ }
+
+ async fn npm_install_package(
+ &mut self,
+ package_name: String,
+ version: String,
+ ) -> wasmtime::Result<Result<(), String>> {
+ convert_result(
+ self.host
+ .node_runtime
+ .npm_install_packages(&self.work_dir(), &[(&package_name, &version)])
+ .await,
+ )
+ }
+
+ async fn latest_github_release(
+ &mut self,
+ repo: String,
+ options: GithubReleaseOptions,
+ ) -> wasmtime::Result<Result<GithubRelease, String>> {
+ convert_result(
+ maybe!(async {
+ let release = util::github::latest_github_release(
+ &repo,
+ options.require_assets,
+ options.pre_release,
+ self.host.http_client.clone(),
+ )
+ .await?;
+ Ok(GithubRelease {
+ version: release.tag_name,
+ assets: release
+ .assets
+ .into_iter()
+ .map(|asset| GithubReleaseAsset {
+ name: asset.name,
+ download_url: asset.browser_download_url,
+ })
+ .collect(),
+ })
+ })
+ .await,
+ )
+ }
+
+ async fn current_platform(&mut self) -> Result<(Os, Architecture)> {
+ Ok((
+ match env::consts::OS {
+ "macos" => Os::Mac,
+ "linux" => Os::Linux,
+ "windows" => Os::Windows,
+ _ => panic!("unsupported os"),
+ },
+ match env::consts::ARCH {
+ "aarch64" => Architecture::Aarch64,
+ "x86" => Architecture::X86,
+ "x86_64" => Architecture::X8664,
+ _ => panic!("unsupported architecture"),
+ },
+ ))
+ }
+
+ async fn set_language_server_installation_status(
+ &mut self,
+ server_name: String,
+ status: LanguageServerInstallationStatus,
+ ) -> wasmtime::Result<()> {
+ let status = match status {
+ LanguageServerInstallationStatus::CheckingForUpdate => {
+ LanguageServerBinaryStatus::CheckingForUpdate
+ }
+ LanguageServerInstallationStatus::Downloading => {
+ LanguageServerBinaryStatus::Downloading
+ }
+ LanguageServerInstallationStatus::None => LanguageServerBinaryStatus::None,
+ LanguageServerInstallationStatus::Failed(error) => {
+ LanguageServerBinaryStatus::Failed { error }
+ }
+ };
+
+ self.host
+ .language_registry
+ .update_lsp_status(language::LanguageServerName(server_name.into()), status);
+ Ok(())
+ }
+
+ async fn download_file(
+ &mut self,
+ url: String,
+ path: String,
+ file_type: DownloadedFileType,
+ ) -> wasmtime::Result<Result<(), String>> {
+ let result = maybe!(async {
+ let path = PathBuf::from(path);
+ let extension_work_dir = self.host.work_dir.join(self.manifest.id.as_ref());
+
+ self.host.fs.create_dir(&extension_work_dir).await?;
+
+ let destination_path = self
+ .host
+ .writeable_path_from_extension(&self.manifest.id, &path)?;
+
+ let mut response = self
+ .host
+ .http_client
+ .get(&url, Default::default(), true)
+ .await
+ .map_err(|err| anyhow!("error downloading release: {}", err))?;
+
+ if !response.status().is_success() {
+ Err(anyhow!(
+ "download failed with status {}",
+ response.status().to_string()
+ ))?;
+ }
+ let body = BufReader::new(response.body_mut());
+
+ match file_type {
+ DownloadedFileType::Uncompressed => {
+ futures::pin_mut!(body);
+ self.host
+ .fs
+ .create_file_with(&destination_path, body)
+ .await?;
+ }
+ DownloadedFileType::Gzip => {
+ let body = GzipDecoder::new(body);
+ futures::pin_mut!(body);
+ self.host
+ .fs
+ .create_file_with(&destination_path, body)
+ .await?;
+ }
+ DownloadedFileType::GzipTar => {
+ let body = GzipDecoder::new(body);
+ futures::pin_mut!(body);
+ self.host
+ .fs
+ .extract_tar_file(&destination_path, Archive::new(body))
+ .await?;
+ }
+ DownloadedFileType::Zip => {
+ let file_name = destination_path
+ .file_name()
+ .ok_or_else(|| anyhow!("invalid download path"))?
+ .to_string_lossy();
+ let zip_filename = format!("{file_name}.zip");
+ let mut zip_path = destination_path.clone();
+ zip_path.set_file_name(zip_filename);
+
+ futures::pin_mut!(body);
+ self.host.fs.create_file_with(&zip_path, body).await?;
+
+ let unzip_status = std::process::Command::new("unzip")
+ .current_dir(&extension_work_dir)
+ .arg(&zip_path)
+ .output()?
+ .status;
+ if !unzip_status.success() {
+ Err(anyhow!("failed to unzip {} archive", path.display()))?;
+ }
+ }
+ }
+
+ Ok(())
+ })
+ .await;
+ convert_result(result)
+ }
+}
+
+fn convert_result<T>(result: Result<T>) -> wasmtime::Result<Result<T, String>> {
+ Ok(result.map_err(|error| error.to_string()))
+}
@@ -1,6 +1,6 @@
[package]
name = "zed_extension_api"
-version = "0.0.1"
+version = "0.0.4"
description = "APIs for creating Zed extensions in Rust"
repository = "https://github.com/zed-industries/zed"
documentation = "https://docs.rs/zed_extension_api"
@@ -15,7 +15,7 @@ workspace = true
path = "src/extension_api.rs"
[dependencies]
-wit-bindgen = "0.18"
+wit-bindgen = "0.22"
[package.metadata.component]
target = { path = "wit" }
@@ -1,6 +1,4 @@
-pub struct Guest;
pub use wit::*;
-
pub type Result<T, E = String> = core::result::Result<T, E>;
pub trait Extension: Send + Sync {
@@ -10,14 +8,14 @@ pub trait Extension: Send + Sync {
fn language_server_command(
&mut self,
- config: wit::LanguageServerConfig,
- worktree: &wit::Worktree,
+ config: LanguageServerConfig,
+ worktree: &Worktree,
) -> Result<Command>;
fn language_server_initialization_options(
&mut self,
- _config: wit::LanguageServerConfig,
- _worktree: &wit::Worktree,
+ _config: LanguageServerConfig,
+ _worktree: &Worktree,
) -> Result<Option<String>> {
Ok(None)
}
@@ -54,11 +52,13 @@ pub static ZED_API_VERSION: [u8; 6] = *include_bytes!(concat!(env!("OUT_DIR"), "
mod wit {
wit_bindgen::generate!({
- exports: { world: super::Component },
- skip: ["init-extension"]
+ skip: ["init-extension"],
+ path: "./wit/0.0.4",
});
}
+wit::export!(Component);
+
struct Component;
impl wit::Guest for Component {
@@ -48,6 +48,9 @@ world extension {
/// Gets the current operating system and architecture
import current-platform: func() -> tuple<os, architecture>;
+ /// Get the path to the node binary used by Zed.
+ import node-binary-path: func() -> result<string, string>;
+
/// Gets the latest version of the given NPM package.
import npm-package-latest-version: func(package-name: string) -> result<string, string>;
@@ -0,0 +1,93 @@
+package zed:extension;
+
+world extension {
+ export init-extension: func();
+
+ record github-release {
+ version: string,
+ assets: list<github-release-asset>,
+ }
+
+ record github-release-asset {
+ name: string,
+ download-url: string,
+ }
+
+ record github-release-options {
+ require-assets: bool,
+ pre-release: bool,
+ }
+
+ enum os {
+ mac,
+ linux,
+ windows,
+ }
+
+ enum architecture {
+ aarch64,
+ x86,
+ x8664,
+ }
+
+ enum downloaded-file-type {
+ gzip,
+ gzip-tar,
+ zip,
+ uncompressed,
+ }
+
+ variant language-server-installation-status {
+ none,
+ downloading,
+ checking-for-update,
+ failed(string),
+ }
+
+ /// Gets the current operating system and architecture
+ import current-platform: func() -> tuple<os, architecture>;
+
+ /// Get the path to the node binary used by Zed.
+ import node-binary-path: func() -> result<string, string>;
+
+ /// Gets the latest version of the given NPM package.
+ import npm-package-latest-version: func(package-name: string) -> result<string, string>;
+
+ /// Returns the installed version of the given NPM package, if it exists.
+ import npm-package-installed-version: func(package-name: string) -> result<option<string>, string>;
+
+ /// Installs the specified NPM package.
+ import npm-install-package: func(package-name: string, version: string) -> result<_, string>;
+
+ /// Gets the latest release for the given GitHub repository.
+ import latest-github-release: func(repo: string, options: github-release-options) -> result<github-release, string>;
+
+ /// Downloads a file from the given url, and saves it to the given filename within the extension's
+ /// working directory. Extracts the file according to the given file type.
+ import download-file: func(url: string, output-filename: string, file-type: downloaded-file-type) -> result<_, string>;
+
+ /// Updates the installation status for the given language server.
+ import set-language-server-installation-status: func(language-server-name: string, status: language-server-installation-status);
+
+ type env-vars = list<tuple<string, string>>;
+
+ record command {
+ command: string,
+ args: list<string>,
+ env: env-vars,
+ }
+
+ resource worktree {
+ read-text-file: func(path: string) -> result<string, string>;
+ which: func(binary-name: string) -> option<string>;
+ shell-env: func() -> env-vars;
+ }
+
+ record language-server-config {
+ name: string,
+ language-name: string,
+ }
+
+ export language-server-command: func(config: language-server-config, worktree: borrow<worktree>) -> result<command, string>;
+ export language-server-initialization-options: func(config: language-server-config, worktree: borrow<worktree>) -> result<option<string>, string>;
+}
@@ -29,6 +29,7 @@ pub fn suggested_extension(file_extension_or_name: &str) -> Option<Arc<str>> {
("git-firefly", "MERGE_MSG"),
("git-firefly", "NOTES_EDITMSG"),
("git-firefly", "TAG_EDITMSG"),
+ ("gleam", "gleam"),
("graphql", "gql"),
("graphql", "graphql"),
("java", "java"),
@@ -39,6 +40,7 @@ pub fn suggested_extension(file_extension_or_name: &str) -> Option<Arc<str>> {
("r", "r"),
("r", "R"),
("sql", "sql"),
+ ("svelte", "svelte"),
("swift", "swift"),
("templ", "templ"),
("wgsl", "wgsl"),
@@ -134,11 +134,15 @@ pub struct CachedLspAdapter {
pub language_ids: HashMap<String, String>,
pub adapter: Arc<dyn LspAdapter>,
pub reinstall_attempt_count: AtomicU64,
+ /// Indicates whether this language server is the primary language server
+ /// for a given language. Currently, most LSP-backed features only work
+ /// with one language server, so one server needs to be primary.
+ pub is_primary: bool,
cached_binary: futures::lock::Mutex<Option<LanguageServerBinary>>,
}
impl CachedLspAdapter {
- pub fn new(adapter: Arc<dyn LspAdapter>) -> Arc<Self> {
+ pub fn new(adapter: Arc<dyn LspAdapter>, is_primary: bool) -> Arc<Self> {
let name = adapter.name();
let disk_based_diagnostic_sources = adapter.disk_based_diagnostic_sources();
let disk_based_diagnostics_progress_token = adapter.disk_based_diagnostics_progress_token();
@@ -150,6 +154,7 @@ impl CachedLspAdapter {
disk_based_diagnostics_progress_token,
language_ids,
adapter,
+ is_primary,
cached_binary: Default::default(),
reinstall_attempt_count: AtomicU64::new(0),
})
@@ -293,7 +298,6 @@ pub trait LspAdapter: 'static + Send + Sync {
.cached_server_binary(container_dir.to_path_buf(), delegate.as_ref())
.await
{
- delegate.update_status(self.name(), LanguageServerBinaryStatus::Cached);
log::info!(
"failed to fetch newest version of language server {:?}. falling back to using {:?}",
self.name(),
@@ -464,7 +468,7 @@ async fn try_fetch_server_binary<L: LspAdapter + 'static + Send + Sync + ?Sized>
.fetch_server_binary(latest_version, container_dir, delegate.as_ref())
.await;
- delegate.update_status(name.clone(), LanguageServerBinaryStatus::Downloaded);
+ delegate.update_status(name.clone(), LanguageServerBinaryStatus::None);
binary
}
@@ -25,7 +25,7 @@ use sum_tree::Bias;
use text::{Point, Rope};
use theme::Theme;
use unicase::UniCase;
-use util::{paths::PathExt, post_inc, ResultExt};
+use util::{maybe, paths::PathExt, post_inc, ResultExt};
pub struct LanguageRegistry {
state: RwLock<LanguageRegistryState>,
@@ -54,10 +54,9 @@ struct LanguageRegistryState {
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum LanguageServerBinaryStatus {
+ None,
CheckingForUpdate,
Downloading,
- Downloaded,
- Cached,
Failed { error: String },
}
@@ -91,9 +90,10 @@ enum AvailableGrammar {
Loaded(#[allow(unused)] PathBuf, tree_sitter::Language),
Loading(
#[allow(unused)] PathBuf,
- Vec<oneshot::Sender<Result<tree_sitter::Language>>>,
+ Vec<oneshot::Sender<Result<tree_sitter::Language, Arc<anyhow::Error>>>>,
),
Unloaded(PathBuf),
+ LoadFailed(Arc<anyhow::Error>),
}
#[derive(Debug)]
@@ -213,7 +213,20 @@ impl LanguageRegistry {
.lsp_adapters
.entry(language_name)
.or_default()
- .push(CachedLspAdapter::new(adapter));
+ .push(CachedLspAdapter::new(adapter, true));
+ }
+
+ pub fn register_secondary_lsp_adapter(
+ &self,
+ language_name: Arc<str>,
+ adapter: Arc<dyn LspAdapter>,
+ ) {
+ self.state
+ .write()
+ .lsp_adapters
+ .entry(language_name)
+ .or_default()
+ .push(CachedLspAdapter::new(adapter, false));
}
#[cfg(any(feature = "test-support", test))]
@@ -227,7 +240,7 @@ impl LanguageRegistry {
.lsp_adapters
.entry(language_name.into())
.or_default()
- .push(CachedLspAdapter::new(Arc::new(adapter)));
+ .push(CachedLspAdapter::new(Arc::new(adapter), true));
self.fake_language_servers(language_name)
}
@@ -578,6 +591,9 @@ impl LanguageRegistry {
if let Some(grammar) = state.grammars.get_mut(name.as_ref()) {
match grammar {
+ AvailableGrammar::LoadFailed(error) => {
+ tx.send(Err(error.clone())).ok();
+ }
AvailableGrammar::Native(grammar) | AvailableGrammar::Loaded(_, grammar) => {
tx.send(Ok(grammar.clone())).ok();
}
@@ -586,46 +602,47 @@ impl LanguageRegistry {
}
AvailableGrammar::Unloaded(wasm_path) => {
let this = self.clone();
+ let wasm_path = wasm_path.clone();
+ *grammar = AvailableGrammar::Loading(wasm_path.clone(), vec![tx]);
self.executor
- .spawn({
- let wasm_path = wasm_path.clone();
- async move {
+ .spawn(async move {
+ let grammar_result = maybe!({
let wasm_bytes = std::fs::read(&wasm_path)?;
let grammar_name = wasm_path
.file_stem()
.and_then(OsStr::to_str)
.ok_or_else(|| anyhow!("invalid grammar filename"))?;
- let grammar = PARSER.with(|parser| {
+ anyhow::Ok(PARSER.with(|parser| {
let mut parser = parser.borrow_mut();
let mut store = parser.take_wasm_store().unwrap();
let grammar = store.load_language(&grammar_name, &wasm_bytes);
parser.set_wasm_store(store).unwrap();
grammar
- })?;
-
- if let Some(AvailableGrammar::Loading(_, txs)) =
- this.state.write().grammars.insert(
- name,
- AvailableGrammar::Loaded(wasm_path, grammar.clone()),
- )
- {
- for tx in txs {
- tx.send(Ok(grammar.clone())).ok();
- }
+ })?)
+ })
+ .map_err(Arc::new);
+
+ let value = match &grammar_result {
+ Ok(grammar) => AvailableGrammar::Loaded(wasm_path, grammar.clone()),
+ Err(error) => AvailableGrammar::LoadFailed(error.clone()),
+ };
+
+ let old_value = this.state.write().grammars.insert(name, value);
+ if let Some(AvailableGrammar::Loading(_, txs)) = old_value {
+ for tx in txs {
+ tx.send(grammar_result.clone()).ok();
}
-
- anyhow::Ok(())
}
})
.detach();
- *grammar = AvailableGrammar::Loading(wasm_path.clone(), vec![tx]);
}
}
} else {
- tx.send(Err(anyhow!("no such grammar {}", name))).ok();
+ tx.send(Err(Arc::new(anyhow!("no such grammar {}", name))))
+ .ok();
}
- async move { rx.await? }
+ async move { rx.await?.map_err(|e| anyhow!(e)) }
}
pub fn to_vec(&self) -> Vec<Arc<Language>> {
@@ -691,7 +708,7 @@ impl LanguageRegistry {
// the login shell to be set on our process.
login_shell_env_loaded.await;
- let binary = adapter
+ let binary_result = adapter
.clone()
.get_language_server_command(
language.clone(),
@@ -699,8 +716,11 @@ impl LanguageRegistry {
delegate.clone(),
&mut cx,
)
- .await?;
+ .await;
+
+ delegate.update_status(adapter.name.clone(), LanguageServerBinaryStatus::None);
+ let binary = binary_result?;
let options = adapter
.adapter
.clone()
@@ -49,7 +49,6 @@ tree-sitter-elixir.workspace = true
tree-sitter-elm.workspace = true
tree-sitter-embedded-template.workspace = true
tree-sitter-erlang.workspace = true
-tree-sitter-gleam.workspace = true
tree-sitter-glsl.workspace = true
tree-sitter-go.workspace = true
tree-sitter-gomod.workspace = true
@@ -75,7 +74,6 @@ tree-sitter-regex.workspace = true
tree-sitter-ruby.workspace = true
tree-sitter-rust.workspace = true
tree-sitter-scheme.workspace = true
-tree-sitter-svelte.workspace = true
tree-sitter-toml.workspace = true
tree-sitter-typescript.workspace = true
tree-sitter-vue.workspace = true
@@ -12,7 +12,7 @@ use std::{
path::{Path, PathBuf},
sync::Arc,
};
-use util::{async_maybe, ResultExt};
+use util::{maybe, ResultExt};
const SERVER_PATH: &str = "node_modules/@astrojs/language-server/bin/nodeServer.js";
@@ -107,7 +107,7 @@ async fn get_cached_server_binary(
container_dir: PathBuf,
node: &dyn NodeRuntime,
) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let mut last_version_dir = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -7,10 +7,9 @@ use lsp::LanguageServerBinary;
use smol::fs::{self, File};
use std::{any::Any, env::consts, path::PathBuf, sync::Arc};
use util::{
- async_maybe,
fs::remove_matching,
github::{latest_github_release, GitHubLspBinaryVersion},
- ResultExt,
+ maybe, ResultExt,
};
pub struct CLspAdapter;
@@ -264,7 +263,7 @@ impl super::LspAdapter for CLspAdapter {
}
async fn get_cached_server_binary(container_dir: PathBuf) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let mut last_clangd_dir = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -9,8 +9,7 @@ use smol::fs;
use std::env::consts::ARCH;
use std::ffi::OsString;
use std::{any::Any, path::PathBuf};
-use util::async_maybe;
-use util::github::latest_github_release;
+use util::{github::latest_github_release, maybe};
use util::{github::GitHubLspBinaryVersion, ResultExt};
pub struct OmniSharpAdapter;
@@ -115,7 +114,7 @@ impl super::LspAdapter for OmniSharpAdapter {
}
async fn get_cached_server_binary(container_dir: PathBuf) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let mut last_binary_path = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -12,7 +12,7 @@ use std::{
path::{Path, PathBuf},
sync::Arc,
};
-use util::{async_maybe, ResultExt};
+use util::{maybe, ResultExt};
const SERVER_PATH: &str =
"node_modules/vscode-langservers-extracted/bin/vscode-css-language-server";
@@ -105,7 +105,7 @@ async fn get_cached_server_binary(
container_dir: PathBuf,
node: &dyn NodeRuntime,
) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let mut last_version_dir = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -11,10 +11,9 @@ use settings::Settings;
use smol::{fs, fs::File};
use std::{any::Any, env::consts, ffi::OsString, path::PathBuf, sync::Arc};
use util::{
- async_maybe,
fs::remove_matching,
github::{latest_github_release, GitHubLspBinaryVersion},
- ResultExt,
+ maybe, ResultExt,
};
#[derive(Clone, Serialize, Deserialize, JsonSchema)]
@@ -207,7 +206,7 @@ impl LspAdapter for DenoLspAdapter {
}
async fn get_cached_server_binary(container_dir: PathBuf) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let mut last = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -11,7 +11,7 @@ use std::{
path::{Path, PathBuf},
sync::Arc,
};
-use util::{async_maybe, ResultExt};
+use util::{maybe, ResultExt};
const SERVER_PATH: &str = "node_modules/dockerfile-language-server-nodejs/bin/docker-langserver";
@@ -94,7 +94,7 @@ async fn get_cached_server_binary(
container_dir: PathBuf,
node: &dyn NodeRuntime,
) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let mut last_version_dir = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -20,10 +20,9 @@ use std::{
};
use task::static_source::{Definition, TaskDefinitions};
use util::{
- async_maybe,
fs::remove_matching,
github::{latest_github_release, GitHubLspBinaryVersion},
- ResultExt,
+ maybe, ResultExt,
};
#[derive(Clone, Serialize, Deserialize, JsonSchema)]
@@ -413,7 +412,7 @@ impl LspAdapter for NextLspAdapter {
}
async fn get_cached_server_binary_next(container_dir: PathBuf) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let mut last_binary_path = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -15,7 +15,7 @@ use std::{
path::{Path, PathBuf},
sync::Arc,
};
-use util::{async_maybe, ResultExt};
+use util::{maybe, ResultExt};
const SERVER_NAME: &str = "elm-language-server";
const SERVER_PATH: &str = "node_modules/@elm-tooling/elm-language-server/out/node/index.js";
@@ -120,7 +120,7 @@ async fn get_cached_server_binary(
container_dir: PathBuf,
node: &dyn NodeRuntime,
) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let mut last_version_dir = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -1,122 +0,0 @@
-use std::any::Any;
-use std::env::consts;
-use std::ffi::OsString;
-use std::path::PathBuf;
-
-use anyhow::{anyhow, bail, Result};
-use async_compression::futures::bufread::GzipDecoder;
-use async_tar::Archive;
-use async_trait::async_trait;
-use futures::io::BufReader;
-use futures::StreamExt;
-use language::{LanguageServerName, LspAdapter, LspAdapterDelegate};
-use lsp::LanguageServerBinary;
-use smol::fs;
-use util::github::{latest_github_release, GitHubLspBinaryVersion};
-use util::{async_maybe, ResultExt};
-
-fn server_binary_arguments() -> Vec<OsString> {
- vec!["lsp".into()]
-}
-
-pub struct GleamLspAdapter;
-
-#[async_trait(?Send)]
-impl LspAdapter for GleamLspAdapter {
- fn name(&self) -> LanguageServerName {
- LanguageServerName("gleam".into())
- }
-
- async fn fetch_latest_server_version(
- &self,
- delegate: &dyn LspAdapterDelegate,
- ) -> Result<Box<dyn 'static + Send + Any>> {
- let release =
- latest_github_release("gleam-lang/gleam", true, false, delegate.http_client()).await?;
- let asset_name = format!(
- "gleam-{version}-{arch}-{os}.tar.gz",
- version = release.tag_name,
- arch = std::env::consts::ARCH,
- os = match consts::OS {
- "macos" => "apple-darwin",
- "linux" => "unknown-linux-musl",
- "windows" => "pc-windows-msvc",
- other => bail!("Running on unsupported os: {other}"),
- },
- );
- let asset = release
- .assets
- .iter()
- .find(|asset| asset.name == asset_name)
- .ok_or_else(|| anyhow!("no asset found matching {:?}", asset_name))?;
- Ok(Box::new(GitHubLspBinaryVersion {
- name: release.tag_name,
- url: asset.browser_download_url.clone(),
- }))
- }
-
- async fn fetch_server_binary(
- &self,
- version: Box<dyn 'static + Send + Any>,
- container_dir: PathBuf,
- delegate: &dyn LspAdapterDelegate,
- ) -> Result<LanguageServerBinary> {
- let version = version.downcast::<GitHubLspBinaryVersion>().unwrap();
- let binary_path = container_dir.join("gleam");
-
- if fs::metadata(&binary_path).await.is_err() {
- let mut response = delegate
- .http_client()
- .get(&version.url, Default::default(), true)
- .await
- .map_err(|err| anyhow!("error downloading release: {}", err))?;
- let decompressed_bytes = GzipDecoder::new(BufReader::new(response.body_mut()));
- let archive = Archive::new(decompressed_bytes);
- archive.unpack(container_dir).await?;
- }
-
- Ok(LanguageServerBinary {
- path: binary_path,
- env: None,
- arguments: server_binary_arguments(),
- })
- }
-
- async fn cached_server_binary(
- &self,
- container_dir: PathBuf,
- _: &dyn LspAdapterDelegate,
- ) -> Option<LanguageServerBinary> {
- get_cached_server_binary(container_dir).await
- }
-
- async fn installation_test_binary(
- &self,
- container_dir: PathBuf,
- ) -> Option<LanguageServerBinary> {
- get_cached_server_binary(container_dir)
- .await
- .map(|mut binary| {
- binary.arguments = vec!["--version".into()];
- binary
- })
- }
-}
-
-async fn get_cached_server_binary(container_dir: PathBuf) -> Option<LanguageServerBinary> {
- async_maybe!({
- let mut last = None;
- let mut entries = fs::read_dir(&container_dir).await?;
- while let Some(entry) = entries.next().await {
- last = Some(entry?.path());
- }
-
- anyhow::Ok(LanguageServerBinary {
- path: last.ok_or_else(|| anyhow!("no cached binary"))?,
- env: None,
- arguments: server_binary_arguments(),
- })
- })
- .await
- .log_err()
-}
@@ -1,11 +0,0 @@
-name = "Gleam"
-grammar = "gleam"
-path_suffixes = ["gleam"]
-line_comments = ["// ", "/// "]
-autoclose_before = ";:.,=}])>"
-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 = ["string", "comment"] },
-]
@@ -1,130 +0,0 @@
-; Comments
-(module_comment) @comment
-(statement_comment) @comment
-(comment) @comment
-
-; Constants
-(constant
- name: (identifier) @constant)
-
-; Modules
-(module) @module
-(import alias: (identifier) @module)
-(remote_type_identifier
- module: (identifier) @module)
-(remote_constructor_name
- module: (identifier) @module)
-((field_access
- record: (identifier) @module
- field: (label) @function)
- (#is-not? local))
-
-; Functions
-(unqualified_import (identifier) @function)
-(unqualified_import "type" (type_identifier) @type)
-(unqualified_import (type_identifier) @constructor)
-(function
- name: (identifier) @function)
-(external_function
- name: (identifier) @function)
-(function_parameter
- name: (identifier) @variable.parameter)
-((function_call
- function: (identifier) @function)
- (#is-not? local))
-((binary_expression
- operator: "|>"
- right: (identifier) @function)
- (#is-not? local))
-
-; "Properties"
-; Assumed to be intended to refer to a name for a field; something that comes
-; before ":" or after "."
-; e.g. record field names, tuple indices, names for named arguments, etc
-(label) @property
-(tuple_access
- index: (integer) @property)
-
-; Attributes
-(attribute
- "@" @attribute
- name: (identifier) @attribute)
-
-(attribute_value (identifier) @constant)
-
-; Type names
-(remote_type_identifier) @type
-(type_identifier) @type
-
-; Data constructors
-(constructor_name) @constructor
-
-; Literals
-(string) @string
-((escape_sequence) @warning
- ; Deprecated in v0.33.0-rc2:
- (#eq? @warning "\\e"))
-(escape_sequence) @string.escape
-(bit_string_segment_option) @function.builtin
-(integer) @number
-(float) @number
-
-; Reserved identifiers
-; TODO: when tree-sitter supports `#any-of?` in the Rust bindings,
-; refactor this to use `#any-of?` rather than `#match?`
-((identifier) @warning
- (#match? @warning "^(auto|delegate|derive|else|implement|macro|test|echo)$"))
-
-; Variables
-(identifier) @variable
-(discard) @comment.unused
-
-; Keywords
-[
- (visibility_modifier) ; "pub"
- (opacity_modifier) ; "opaque"
- "as"
- "assert"
- "case"
- "const"
- ; DEPRECATED: 'external' was removed in v0.30.
- "external"
- "fn"
- "if"
- "import"
- "let"
- "panic"
- "todo"
- "type"
- "use"
-] @keyword
-
-; Operators
-(binary_expression
- operator: _ @operator)
-(boolean_negation "!" @operator)
-(integer_negation "-" @operator)
-
-; Punctuation
-[
- "("
- ")"
- "["
- "]"
- "{"
- "}"
- "<<"
- ">>"
-] @punctuation.bracket
-[
- "."
- ","
- ;; Controversial -- maybe some are operators?
- ":"
- "#"
- "="
- "->"
- ".."
- "-"
- "<-"
-] @punctuation.delimiter
@@ -1,3 +0,0 @@
-(_ "[" "]" @end) @indent
-(_ "{" "}" @end) @indent
-(_ "(" ")" @end) @indent
@@ -1,31 +0,0 @@
-(external_type
- (visibility_modifier)? @context
- "type" @context
- (type_name) @name) @item
-
-(type_definition
- (visibility_modifier)? @context
- (opacity_modifier)? @context
- "type" @context
- (type_name) @name) @item
-
-(data_constructor
- (constructor_name) @name) @item
-
-(data_constructor_argument
- (label) @name) @item
-
-(type_alias
- (visibility_modifier)? @context
- "type" @context
- (type_name) @name) @item
-
-(function
- (visibility_modifier)? @context
- "fn" @context
- name: (_) @name) @item
-
-(constant
- (visibility_modifier)? @context
- "const" @context
- name: (_) @name) @item
@@ -19,7 +19,7 @@ use std::{
Arc,
},
};
-use util::{async_maybe, fs::remove_matching, github::latest_github_release, ResultExt};
+use util::{fs::remove_matching, github::latest_github_release, maybe, ResultExt};
fn server_binary_arguments() -> Vec<OsString> {
vec!["-mode=stdio".into()]
@@ -368,7 +368,7 @@ impl super::LspAdapter for GoLspAdapter {
}
async fn get_cached_server_binary(container_dir: PathBuf) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let mut last_binary_path = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -12,7 +12,7 @@ use std::{
path::{Path, PathBuf},
sync::Arc,
};
-use util::{async_maybe, ResultExt};
+use util::{maybe, ResultExt};
const SERVER_PATH: &str =
"node_modules/vscode-langservers-extracted/bin/vscode-html-language-server";
@@ -105,7 +105,7 @@ async fn get_cached_server_binary(
container_dir: PathBuf,
node: &dyn NodeRuntime,
) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let mut last_version_dir = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -16,7 +16,7 @@ use std::{
path::{Path, PathBuf},
sync::{Arc, OnceLock},
};
-use util::{async_maybe, paths, ResultExt};
+use util::{maybe, paths, ResultExt};
const SERVER_PATH: &str = "node_modules/vscode-json-languageserver/bin/vscode-json-languageserver";
@@ -167,7 +167,7 @@ async fn get_cached_server_binary(
container_dir: PathBuf,
node: &dyn NodeRuntime,
) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let mut last_version_dir = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -22,7 +22,6 @@ mod dockerfile;
mod elixir;
mod elm;
mod erlang;
-mod gleam;
mod go;
mod haskell;
mod html;
@@ -36,7 +35,6 @@ mod purescript;
mod python;
mod ruby;
mod rust;
-mod svelte;
mod tailwind;
mod terraform;
mod toml;
@@ -83,7 +81,6 @@ pub fn init(
tree_sitter_embedded_template::language(),
),
("erlang", tree_sitter_erlang::language()),
- ("gleam", tree_sitter_gleam::language()),
("glsl", tree_sitter_glsl::language()),
("go", tree_sitter_go::language()),
("gomod", tree_sitter_gomod::language()),
@@ -113,7 +110,6 @@ pub fn init(
("ruby", tree_sitter_ruby::language()),
("rust", tree_sitter_rust::language()),
("scheme", tree_sitter_scheme::language()),
- ("svelte", tree_sitter_svelte::language()),
("toml", tree_sitter_toml::language()),
("tsx", tree_sitter_typescript::language_tsx()),
("typescript", tree_sitter_typescript::language_typescript()),
@@ -237,8 +233,6 @@ pub fn init(
}
}
language!("erlang", vec![Arc::new(erlang::ErlangLspAdapter)]);
-
- language!("gleam", vec![Arc::new(gleam::GleamLspAdapter)]);
language!("go", vec![Arc::new(go::GoLspAdapter)]);
language!("gomod");
language!("gowork");
@@ -346,13 +340,6 @@ pub fn init(
"yaml",
vec![Arc::new(yaml::YamlLspAdapter::new(node_runtime.clone()))]
);
- language!(
- "svelte",
- vec![
- Arc::new(svelte::SvelteLspAdapter::new(node_runtime.clone())),
- Arc::new(tailwind::TailwindLspAdapter::new(node_runtime.clone())),
- ]
- );
language!(
"php",
vec![
@@ -393,6 +380,11 @@ pub fn init(
))]
);
language!("dart", vec![Arc::new(dart::DartLanguageServer {})]);
+
+ languages.register_secondary_lsp_adapter(
+ "Svelte".into(),
+ Arc::new(tailwind::TailwindLspAdapter::new(node_runtime.clone())),
+ );
}
#[cfg(any(test, feature = "test-support"))]
@@ -8,9 +8,8 @@ use lsp::LanguageServerBinary;
use smol::fs;
use std::{any::Any, env::consts, path::PathBuf};
use util::{
- async_maybe,
github::{latest_github_release, GitHubLspBinaryVersion},
- ResultExt,
+ maybe, ResultExt,
};
#[derive(Copy, Clone)]
@@ -117,7 +116,7 @@ impl super::LspAdapter for LuaLspAdapter {
}
async fn get_cached_server_binary(container_dir: PathBuf) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let mut last_binary_path = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -14,7 +14,7 @@ use std::{
path::{Path, PathBuf},
sync::Arc,
};
-use util::{async_maybe, ResultExt};
+use util::{maybe, ResultExt};
fn intelephense_server_binary_arguments(server_path: &Path) -> Vec<OsString> {
vec![server_path.into(), "--stdio".into()]
@@ -106,7 +106,7 @@ async fn get_cached_server_binary(
container_dir: PathBuf,
node: &dyn NodeRuntime,
) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let mut last_version_dir = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -11,7 +11,7 @@ use std::{
path::{Path, PathBuf},
sync::Arc,
};
-use util::{async_maybe, ResultExt};
+use util::{maybe, ResultExt};
const SERVER_PATH: &str = "node_modules/.bin/prisma-language-server";
@@ -94,7 +94,7 @@ async fn get_cached_server_binary(
container_dir: PathBuf,
node: &dyn NodeRuntime,
) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let mut last_version_dir = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -13,7 +13,7 @@ use std::{
path::{Path, PathBuf},
sync::Arc,
};
-use util::{async_maybe, ResultExt};
+use util::{maybe, ResultExt};
const SERVER_PATH: &str = "node_modules/.bin/purescript-language-server";
@@ -115,7 +115,7 @@ async fn get_cached_server_binary(
container_dir: PathBuf,
node: &dyn NodeRuntime,
) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let mut last_version_dir = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -16,10 +16,9 @@ use task::{
TaskVariables,
};
use util::{
- async_maybe,
fs::remove_matching,
github::{latest_github_release, GitHubLspBinaryVersion},
- ResultExt,
+ maybe, ResultExt,
};
pub struct RustLspAdapter;
@@ -397,7 +396,7 @@ impl ContextProvider for RustContextProvider {
}
async fn get_cached_server_binary(container_dir: PathBuf) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let mut last = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -1,162 +0,0 @@
-use anyhow::{anyhow, Result};
-use async_trait::async_trait;
-use futures::StreamExt;
-use language::{LanguageServerName, LspAdapter, LspAdapterDelegate};
-use lsp::LanguageServerBinary;
-use node_runtime::NodeRuntime;
-use serde_json::json;
-use smol::fs;
-use std::{
- any::Any,
- ffi::OsString,
- path::{Path, PathBuf},
- sync::Arc,
-};
-use util::{async_maybe, ResultExt};
-
-const SERVER_PATH: &str = "node_modules/svelte-language-server/bin/server.js";
-
-fn server_binary_arguments(server_path: &Path) -> Vec<OsString> {
- vec![server_path.into(), "--stdio".into()]
-}
-
-pub struct SvelteLspAdapter {
- node: Arc<dyn NodeRuntime>,
-}
-
-impl SvelteLspAdapter {
- pub fn new(node: Arc<dyn NodeRuntime>) -> Self {
- SvelteLspAdapter { node }
- }
-}
-
-#[async_trait(?Send)]
-impl LspAdapter for SvelteLspAdapter {
- fn name(&self) -> LanguageServerName {
- LanguageServerName("svelte-language-server".into())
- }
-
- async fn fetch_latest_server_version(
- &self,
- _: &dyn LspAdapterDelegate,
- ) -> Result<Box<dyn 'static + Any + Send>> {
- Ok(Box::new(
- self.node
- .npm_package_latest_version("svelte-language-server")
- .await?,
- ) as Box<_>)
- }
-
- async fn fetch_server_binary(
- &self,
- latest_version: Box<dyn 'static + Send + Any>,
- container_dir: PathBuf,
- _: &dyn LspAdapterDelegate,
- ) -> Result<LanguageServerBinary> {
- let latest_version = latest_version.downcast::<String>().unwrap();
- let server_path = container_dir.join(SERVER_PATH);
- let package_name = "svelte-language-server";
-
- let should_install_language_server = self
- .node
- .should_install_npm_package(package_name, &server_path, &container_dir, &latest_version)
- .await;
-
- if should_install_language_server {
- self.node
- .npm_install_packages(&container_dir, &[(package_name, latest_version.as_str())])
- .await?;
- }
-
- Ok(LanguageServerBinary {
- path: self.node.binary_path().await?,
- env: None,
- arguments: server_binary_arguments(&server_path),
- })
- }
-
- async fn cached_server_binary(
- &self,
- container_dir: PathBuf,
- _: &dyn LspAdapterDelegate,
- ) -> Option<LanguageServerBinary> {
- get_cached_server_binary(container_dir, &*self.node).await
- }
-
- async fn installation_test_binary(
- &self,
- container_dir: PathBuf,
- ) -> Option<LanguageServerBinary> {
- get_cached_server_binary(container_dir, &*self.node).await
- }
-
- async fn initialization_options(
- self: Arc<Self>,
- _: &Arc<dyn LspAdapterDelegate>,
- ) -> Result<Option<serde_json::Value>> {
- let config = json!({
- "inlayHints": {
- "parameterNames": {
- "enabled": "all",
- "suppressWhenArgumentMatchesName": false
- },
- "parameterTypes": {
- "enabled": true
- },
- "variableTypes": {
- "enabled": true,
- "suppressWhenTypeMatchesName": false
- },
- "propertyDeclarationTypes": {
- "enabled": true
- },
- "functionLikeReturnType": {
- "enabled": true
- },
- "enumMemberValues": {
- "enabled": true
- }
- }
- });
-
- Ok(Some(json!({
- "provideFormatter": true,
- "configuration": {
- "typescript": config,
- "javascript": config
- }
- })))
- }
-}
-
-async fn get_cached_server_binary(
- container_dir: PathBuf,
- node: &dyn NodeRuntime,
-) -> Option<LanguageServerBinary> {
- async_maybe!({
- let mut last_version_dir = None;
- let mut entries = fs::read_dir(&container_dir).await?;
- while let Some(entry) = entries.next().await {
- let entry = entry?;
- if entry.file_type().await?.is_dir() {
- last_version_dir = Some(entry.path());
- }
- }
- let last_version_dir = last_version_dir.ok_or_else(|| anyhow!("no cached binary"))?;
- let server_path = last_version_dir.join(SERVER_PATH);
- if server_path.exists() {
- Ok(LanguageServerBinary {
- path: node.binary_path().await?,
- env: None,
- arguments: server_binary_arguments(&server_path),
- })
- } else {
- Err(anyhow!(
- "missing executable in directory {:?}",
- last_version_dir
- ))
- }
- })
- .await
- .log_err()
-}
@@ -1,9 +0,0 @@
-[
- (style_element)
- (script_element)
- (element)
- (if_statement)
- (else_statement)
- (each_statement)
- (await_statement)
-] @fold
@@ -14,7 +14,7 @@ use std::{
path::{Path, PathBuf},
sync::Arc,
};
-use util::{async_maybe, ResultExt};
+use util::{maybe, ResultExt};
const SERVER_PATH: &str = "node_modules/.bin/tailwindcss-language-server";
@@ -135,7 +135,7 @@ async fn get_cached_server_binary(
container_dir: PathBuf,
node: &dyn NodeRuntime,
) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let mut last_version_dir = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -7,10 +7,9 @@ use lsp::{CodeActionKind, LanguageServerBinary};
use smol::fs::{self, File};
use std::{any::Any, ffi::OsString, path::PathBuf};
use util::{
- async_maybe,
fs::remove_matching,
github::{latest_github_release, GitHubLspBinaryVersion},
- ResultExt,
+ maybe, ResultExt,
};
fn terraform_ls_binary_arguments() -> Vec<OsString> {
@@ -154,7 +153,7 @@ fn build_download_url(version: String) -> Result<String> {
}
async fn get_cached_server_binary(container_dir: PathBuf) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let mut last = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -6,8 +6,8 @@ use language::{LanguageServerName, LspAdapter, LspAdapterDelegate};
use lsp::LanguageServerBinary;
use smol::fs::{self, File};
use std::{any::Any, path::PathBuf};
-use util::async_maybe;
use util::github::latest_github_release;
+use util::maybe;
use util::{github::GitHubLspBinaryVersion, ResultExt};
pub struct TaploLspAdapter;
@@ -108,7 +108,7 @@ impl LspAdapter for TaploLspAdapter {
}
async fn get_cached_server_binary(container_dir: PathBuf) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let mut last = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -18,10 +18,9 @@ use std::{
sync::Arc,
};
use util::{
- async_maybe,
fs::remove_matching,
github::{build_tarball_url, GitHubLspBinaryVersion},
- ResultExt,
+ maybe, ResultExt,
};
fn typescript_server_binary_arguments(server_path: &Path) -> Vec<OsString> {
@@ -199,7 +198,7 @@ async fn get_cached_ts_server_binary(
container_dir: PathBuf,
node: &dyn NodeRuntime,
) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let old_server_path = container_dir.join(TypeScriptLspAdapter::OLD_SERVER_PATH);
let new_server_path = container_dir.join(TypeScriptLspAdapter::NEW_SERVER_PATH);
if new_server_path.exists() {
@@ -378,7 +377,7 @@ async fn get_cached_eslint_server_binary(
container_dir: PathBuf,
node: &dyn NodeRuntime,
) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
// This is unfortunate but we don't know what the version is to build a path directly
let mut dir = fs::read_dir(&container_dir).await?;
let first = dir.next().await.ok_or(anyhow!("missing first file"))??;
@@ -12,7 +12,7 @@ use std::{
path::{Path, PathBuf},
sync::Arc,
};
-use util::{async_maybe, ResultExt};
+use util::{maybe, ResultExt};
pub struct VueLspVersion {
vue_version: String,
@@ -211,7 +211,7 @@ async fn get_cached_server_binary(
container_dir: PathBuf,
node: Arc<dyn NodeRuntime>,
) -> Option<(LanguageServerBinary, TypescriptPath)> {
- async_maybe!({
+ maybe!(async {
let mut last_version_dir = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -15,7 +15,7 @@ use std::{
path::{Path, PathBuf},
sync::Arc,
};
-use util::{async_maybe, ResultExt};
+use util::{maybe, ResultExt};
const SERVER_PATH: &str = "node_modules/yaml-language-server/bin/yaml-language-server";
@@ -110,7 +110,7 @@ async fn get_cached_server_binary(
container_dir: PathBuf,
node: &dyn NodeRuntime,
) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let mut last_version_dir = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -9,8 +9,8 @@ use lsp::LanguageServerBinary;
use smol::fs;
use std::env::consts::{ARCH, OS};
use std::{any::Any, path::PathBuf};
-use util::async_maybe;
use util::github::latest_github_release;
+use util::maybe;
use util::{github::GitHubLspBinaryVersion, ResultExt};
pub struct ZlsAdapter;
@@ -113,7 +113,7 @@ impl LspAdapter for ZlsAdapter {
}
async fn get_cached_server_binary(container_dir: PathBuf) -> Option<LanguageServerBinary> {
- async_maybe!({
+ maybe!(async {
let mut last_binary_path = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
@@ -9149,7 +9149,8 @@ impl Project {
buffer: &Buffer,
cx: &AppContext,
) -> Option<(&Arc<CachedLspAdapter>, &Arc<LanguageServer>)> {
- self.language_servers_for_buffer(buffer, cx).next()
+ self.language_servers_for_buffer(buffer, cx)
+ .find(|s| s.0.is_primary)
}
pub fn language_server_for_buffer(
@@ -426,21 +426,20 @@ pub fn unzip_option<T, U>(option: Option<(T, U)>) -> (Option<T>, Option<U>) {
}
}
-/// Evaluates to an immediately invoked function expression. Good for using the ? operator
-/// in functions which do not return an Option or Result
+/// Expands to an immediately-invoked function expression. Good for using the ? operator
+/// in functions which do not return an Option or Result.
+///
+/// Accepts a normal block, an async block, or an async move block.
#[macro_export]
macro_rules! maybe {
($block:block) => {
(|| $block)()
};
-}
-
-/// Evaluates to an immediately invoked function expression. Good for using the ? operator
-/// in functions which do not return an Option or Result, but async.
-#[macro_export]
-macro_rules! async_maybe {
- ($block:block) => {
- (|| async move { $block })()
+ (async $block:block) => {
+ (|| async $block)()
+ };
+ (async move $block:block) => {
+ (|| async move $block)()
};
}
@@ -184,7 +184,7 @@ impl LanguageServerPrompt {
}
async fn select_option(this: View<Self>, ix: usize, mut cx: AsyncWindowContext) {
- util::async_maybe!({
+ util::maybe!(async move {
let potential_future = this.update(&mut cx, |this, _| {
this.request.take().map(|request| request.respond(ix))
});
@@ -47,8 +47,8 @@ use std::{
};
use theme::{ActiveTheme, SystemAppearance, ThemeRegistry, ThemeSettings};
use util::{
- async_maybe,
http::{HttpClient, HttpClientWithUrl},
+ maybe,
paths::{self, CRASHES_DIR, CRASHES_RETIRED_DIR},
ResultExt, TryFutureExt,
};
@@ -455,7 +455,7 @@ async fn installation_id() -> Result<(String, bool)> {
}
async fn restore_or_create_workspace(app_state: Arc<AppState>, cx: AsyncAppContext) {
- async_maybe!({
+ maybe!(async {
if let Some(location) = workspace::last_opened_workspace_paths().await {
cx.update(|cx| {
workspace::open_paths(
@@ -8,9 +8,9 @@ license = "Apache-2.0"
[lints]
workspace = true
-[dependencies]
-zed_extension_api = { path = "../../crates/extension_api" }
-
[lib]
path = "src/gleam.rs"
crate-type = ["cdylib"]
+
+[dependencies]
+zed_extension_api = "0.0.4"
@@ -9,10 +9,6 @@ impl GleamExtension {
fn language_server_binary_path(&mut self, config: zed::LanguageServerConfig) -> Result<String> {
if let Some(path) = &self.cached_binary_path {
if fs::metadata(path).map_or(false, |stat| stat.is_file()) {
- zed::set_language_server_installation_status(
- &config.name,
- &zed::LanguageServerInstallationStatus::Cached,
- );
return Ok(path.clone());
}
}
@@ -75,11 +71,6 @@ impl GleamExtension {
fs::remove_dir_all(&entry.path()).ok();
}
}
-
- zed::set_language_server_installation_status(
- &config.name,
- &zed::LanguageServerInstallationStatus::Downloaded,
- );
}
self.cached_binary_path = Some(binary_path.clone());
@@ -0,0 +1,3 @@
+target
+*.wasm
+grammars
@@ -0,0 +1,16 @@
+[package]
+name = "zed_svelte"
+version = "0.0.1"
+edition = "2021"
+publish = false
+license = "Apache-2.0"
+
+[lints]
+workspace = true
+
+[lib]
+path = "src/svelte.rs"
+crate-type = ["cdylib"]
+
+[dependencies]
+zed_extension_api = "0.0.4"
@@ -0,0 +1,15 @@
+id = "svelte"
+name = "Svelte"
+description = "Svelte support"
+version = "0.0.1"
+schema_version = 1
+authors = []
+repository = "https://github.com/zed-extensions/svelte"
+
+[language_servers.svelte-language-server]
+name = "Svelte Language Server"
+language = "Svelte"
+
+[grammars.svelte]
+repository = "https://github.com/Himujjal/tree-sitter-svelte"
+commit = "ea528fc9985aed8d93c9f438c185644a33d011af"
@@ -0,0 +1,126 @@
+use std::{env, fs};
+use zed_extension_api::{self as zed, Result};
+
+struct SvelteExtension {
+ did_find_server: bool,
+}
+
+const SERVER_PATH: &str = "node_modules/svelte-language-server/bin/server.js";
+const PACKAGE_NAME: &str = "svelte-language-server";
+
+impl SvelteExtension {
+ fn server_exists(&self) -> bool {
+ fs::metadata(SERVER_PATH).map_or(false, |stat| stat.is_file())
+ }
+
+ fn server_script_path(&mut self, config: zed::LanguageServerConfig) -> Result<String> {
+ let server_exists = self.server_exists();
+ if self.did_find_server && server_exists {
+ return Ok(SERVER_PATH.to_string());
+ }
+
+ zed::set_language_server_installation_status(
+ &config.name,
+ &zed::LanguageServerInstallationStatus::CheckingForUpdate,
+ );
+ let version = zed::npm_package_latest_version(PACKAGE_NAME)?;
+
+ if !server_exists
+ || zed::npm_package_installed_version(PACKAGE_NAME)?.as_ref() != Some(&version)
+ {
+ zed::set_language_server_installation_status(
+ &config.name,
+ &zed::LanguageServerInstallationStatus::Downloading,
+ );
+ let result = zed::npm_install_package(PACKAGE_NAME, &version);
+ match result {
+ Ok(()) => {
+ if !self.server_exists() {
+ Err(format!(
+ "installed package '{PACKAGE_NAME}' did not contain expected path '{SERVER_PATH}'",
+ ))?;
+ }
+ }
+ Err(error) => {
+ if !self.server_exists() {
+ Err(error)?;
+ }
+ }
+ }
+ }
+
+ self.did_find_server = true;
+ Ok(SERVER_PATH.to_string())
+ }
+}
+
+impl zed::Extension for SvelteExtension {
+ fn new() -> Self {
+ Self {
+ did_find_server: false,
+ }
+ }
+
+ fn language_server_command(
+ &mut self,
+ config: zed::LanguageServerConfig,
+ _: &zed::Worktree,
+ ) -> Result<zed::Command> {
+ let server_path = self.server_script_path(config)?;
+ Ok(zed::Command {
+ command: zed::node_binary_path()?,
+ args: vec![
+ env::current_dir()
+ .unwrap()
+ .join(&server_path)
+ .to_string_lossy()
+ .to_string(),
+ "--stdio".to_string(),
+ ],
+ env: Default::default(),
+ })
+ }
+
+ fn language_server_initialization_options(
+ &mut self,
+ _: zed::LanguageServerConfig,
+ _: &zed::Worktree,
+ ) -> Result<Option<String>> {
+ let config = r#"{
+ "inlayHints": {
+ "parameterNames": {
+ "enabled": "all",
+ "suppressWhenArgumentMatchesName": false
+ },
+ "parameterTypes": {
+ "enabled": true
+ },
+ "variableTypes": {
+ "enabled": true,
+ "suppressWhenTypeMatchesName": false
+ },
+ "propertyDeclarationTypes": {
+ "enabled": true
+ },
+ "functionLikeReturnType": {
+ "enabled": true
+ },
+ "enumMemberValues": {
+ "enabled": true
+ }
+ }
+ }"#;
+
+ Ok(Some(format!(
+ r#"{{
+ "provideFormatter": true,
+ "configuration": {{
+ "typescript": {config},
+ "javascript": {config}
+ }}
+ }}"#
+ )))
+ }
+}
+
+zed::register_extension!(SvelteExtension);
@@ -8,9 +8,9 @@ license = "Apache-2.0"
[lints]
workspace = true
-[dependencies]
-zed_extension_api = { path = "../../crates/extension_api" }
-
[lib]
path = "src/uiua.rs"
crate-type = ["cdylib"]
+
+[dependencies]
+zed_extension_api = "0.0.4"