Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #132030 - matthiaskrgr:rollup-1g6quh0, r=matthiaskrgr
Rollup of 3 pull requests Successful merges: - #131918 (coverage: Make counter creation handle node/edge counters more uniformly) - #132021 (nuttx.md: typo) - #132029 (Subtree update of `rust-analyzer`) r? `@ghost` `@rustbot` modify labels: rollup
bors 2024-10-22
parent 8c3495a · parent 81d6960 · commit 9f433d2
-rw-r--r--.editorconfig2
-rw-r--r--.github/workflows/ci.yaml6
-rw-r--r--Cargo.lock86
-rw-r--r--Cargo.toml14
-rw-r--r--crates/hir-def/src/data.rs8
-rw-r--r--crates/hir-def/src/item_tree.rs4
-rw-r--r--crates/hir-def/src/item_tree/lower.rs8
-rw-r--r--crates/hir-def/src/item_tree/pretty.rs19
-rw-r--r--crates/hir-def/src/visibility.rs6
-rw-r--r--crates/hir-expand/src/builtin/fn_macro.rs25
-rw-r--r--crates/hir-expand/src/db.rs2
-rw-r--r--crates/hir-ty/src/consteval/tests.rs7
-rw-r--r--crates/hir-ty/src/diagnostics/unsafe_check.rs2
-rw-r--r--crates/hir-ty/src/infer/unify.rs12
-rw-r--r--crates/hir-ty/src/layout.rs20
-rw-r--r--crates/hir-ty/src/lib.rs12
-rw-r--r--crates/hir-ty/src/utils.rs12
-rw-r--r--crates/hir/src/semantics.rs52
-rw-r--r--crates/hir/src/semantics/source_to_def.rs28
-rw-r--r--crates/ide-assists/src/handlers/bool_to_enum.rs3
-rw-r--r--crates/ide-assists/src/handlers/unwrap_result_return_type.rs1115
-rw-r--r--crates/ide-assists/src/handlers/unwrap_return_type.rs2229
-rw-r--r--crates/ide-assists/src/handlers/wrap_return_type.rs2457
-rw-r--r--crates/ide-assists/src/handlers/wrap_return_type_in_result.rs1268
-rw-r--r--crates/ide-assists/src/lib.rs8
-rw-r--r--crates/ide-assists/src/tests/generated.rs28
-rw-r--r--crates/ide-completion/src/completions/item_list.rs126
-rw-r--r--crates/ide-completion/src/completions/keyword.rs1
-rw-r--r--crates/ide-completion/src/context.rs8
-rw-r--r--crates/ide-completion/src/context/analysis.rs10
-rw-r--r--crates/ide-completion/src/render.rs2
-rw-r--r--crates/ide-completion/src/tests/item_list.rs55
-rw-r--r--crates/ide-completion/src/tests/pattern.rs18
-rw-r--r--crates/ide-diagnostics/src/handlers/missing_unsafe.rs35
-rw-r--r--crates/ide/src/annotations.rs238
-rw-r--r--crates/ide/src/goto_definition.rs38
-rw-r--r--crates/ide/src/references.rs21
-rw-r--r--crates/ide/src/runnables.rs12
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html12
-rw-r--r--crates/mbe/src/benchmark.rs13
-rw-r--r--crates/parser/src/grammar/items.rs6
-rw-r--r--crates/parser/src/syntax_kind/generated.rs6
-rw-r--r--crates/parser/test_data/parser/ok/0073_safe_declarations_in_extern_blocks.rast208
-rw-r--r--crates/parser/test_data/parser/ok/0073_safe_declarations_in_extern_blocks.rs17
-rw-r--r--crates/project-model/src/tests.rs3
-rw-r--r--crates/ra-salsa/Cargo.toml2
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs9
-rw-r--r--crates/rust-analyzer/src/cli/flags.rs3
-rw-r--r--crates/rust-analyzer/src/lsp/from_proto.rs12
-rw-r--r--crates/syntax/rust.ungram3
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs6
-rw-r--r--crates/syntax/src/ptr.rs2
-rw-r--r--docs/user/generated_config.adoc44
-rw-r--r--editors/code/package-lock.json1525
-rw-r--r--editors/code/package.json53
-rw-r--r--editors/code/src/config.ts4
-rw-r--r--editors/code/src/debug.ts43
-rw-r--r--editors/code/src/main.ts9
-rw-r--r--lib/line-index/Cargo.toml2
-rw-r--r--lib/line-index/src/lib.rs8
-rw-r--r--lib/line-index/src/tests.rs23
-rw-r--r--rust-version2
-rw-r--r--xtask/src/codegen/grammar/ast_src.rs2
63 files changed, 7101 insertions, 2913 deletions
diff --git a/.editorconfig b/.editorconfig
index e337066f7e..6bb743a673 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -13,5 +13,5 @@ max_line_length = 100
[*.md]
indent_size = 2
-[*.{yml, yaml}]
+[*.{yml,yaml}]
indent_size = 2
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 6d3e488bb0..5cf4a8fd43 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -104,11 +104,11 @@ jobs:
if: matrix.os == 'ubuntu-latest'
run: target/${{ matrix.target }}/debug/rust-analyzer analysis-stats .
- - name: Run analysis-stats on rust std library
+ - name: Run analysis-stats on the rust standard libraries
if: matrix.os == 'ubuntu-latest'
env:
- RUSTC_BOOTSTRAP: 1
- run: target/${{ matrix.target }}/debug/rust-analyzer analysis-stats --with-deps $(rustc --print sysroot)/lib/rustlib/src/rust/library/std
+ RUSTC_BOOTSTRAP: 1
+ run: target/${{ matrix.target }}/debug/rust-analyzer analysis-stats --with-deps --no-sysroot --no-test $(rustc --print sysroot)/lib/rustlib/src/rust/library/
- name: clippy
if: matrix.os == 'windows-latest'
diff --git a/Cargo.lock b/Cargo.lock
index 4a6da47a47..fd569571b3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -73,7 +73,7 @@ dependencies = [
"intern",
"la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lz4_flex",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"salsa",
"semver",
"span",
@@ -161,7 +161,7 @@ dependencies = [
"expect-test",
"intern",
"oorandom",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"syntax",
"syntax-bridge",
"tt",
@@ -216,7 +216,7 @@ dependencies = [
"chalk-derive",
"chalk-ir",
"chalk-solve",
- "rustc-hash",
+ "rustc-hash 1.1.0",
"tracing",
]
@@ -232,7 +232,7 @@ dependencies = [
"indexmap",
"itertools",
"petgraph",
- "rustc-hash",
+ "rustc-hash 1.1.0",
"tracing",
]
@@ -513,7 +513,7 @@ dependencies = [
"hir-ty",
"intern",
"itertools",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"smallvec",
"span",
"stdx",
@@ -547,7 +547,7 @@ dependencies = [
"mbe",
"ra-ap-rustc_abi",
"ra-ap-rustc_parse_format",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"rustc_apfloat",
"smallvec",
"span",
@@ -577,7 +577,7 @@ dependencies = [
"limit",
"mbe",
"parser",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"smallvec",
"span",
"stdx",
@@ -616,7 +616,7 @@ dependencies = [
"ra-ap-rustc_abi",
"ra-ap-rustc_index",
"ra-ap-rustc_pattern_analysis",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"rustc_apfloat",
"scoped-tls",
"smallvec",
@@ -731,13 +731,13 @@ dependencies = [
"indexmap",
"itertools",
"limit",
- "line-index 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "line-index 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr",
"nohash-hasher",
"parser",
"profile",
"rayon",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"span",
"stdx",
"syntax",
@@ -834,7 +834,7 @@ version = "0.0.0"
dependencies = [
"dashmap",
"hashbrown",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"sptr",
"triomphe",
]
@@ -939,7 +939,7 @@ version = "0.0.0"
[[package]]
name = "line-index"
-version = "0.1.1"
+version = "0.1.2"
dependencies = [
"nohash-hasher",
"oorandom",
@@ -948,9 +948,9 @@ dependencies = [
[[package]]
name = "line-index"
-version = "0.1.1"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67d61795376ae2683928c218fda7d7d7db136fd38c06b7552904667f0d55580a"
+checksum = "3e27e0ed5a392a7f5ba0b3808a2afccff16c64933312c84b57618b49d1209bd2"
dependencies = [
"nohash-hasher",
"text-size",
@@ -1051,7 +1051,7 @@ dependencies = [
"intern",
"parser",
"ra-ap-rustc_lexer",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"smallvec",
"span",
"stdx",
@@ -1345,7 +1345,7 @@ dependencies = [
"indexmap",
"intern",
"paths",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"serde",
"serde_json",
"span",
@@ -1435,7 +1435,7 @@ dependencies = [
"itertools",
"la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"paths",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"semver",
"serde",
"serde_json",
@@ -1497,9 +1497,9 @@ dependencies = [
[[package]]
name = "ra-ap-rustc_abi"
-version = "0.71.0"
+version = "0.73.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6999d098000b98415939f13158dac78cb3eeeb7b0c073847f3e4b623866e27c"
+checksum = "879ece0781e3c1cb670b9f29775c81a43a16db789d1296fad6bc5c74065b2fac"
dependencies = [
"bitflags 2.6.0",
"ra-ap-rustc_index",
@@ -1508,9 +1508,9 @@ dependencies = [
[[package]]
name = "ra-ap-rustc_index"
-version = "0.71.0"
+version = "0.73.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae9fb312d942817dab10790881f555928c1f6a11a85186e8e573ad4a86c7d3be"
+checksum = "6910087ff89bb9f3db114bfcd86b5139042731fe7278d3ff4ceaa69a140154a7"
dependencies = [
"arrayvec",
"ra-ap-rustc_index_macros",
@@ -1519,9 +1519,9 @@ dependencies = [
[[package]]
name = "ra-ap-rustc_index_macros"
-version = "0.71.0"
+version = "0.73.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "766e3990eb1066a06deefc561b5a01b32ca5c9211feea31cbf4ed50611519872"
+checksum = "3b6f7bd12b678fbb37444ba77f3b0cfc13b7394a6dc7b0c799491fc9df0a9997"
dependencies = [
"proc-macro2",
"quote",
@@ -1530,9 +1530,9 @@ dependencies = [
[[package]]
name = "ra-ap-rustc_lexer"
-version = "0.71.0"
+version = "0.73.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4afa98eb7889c137d5a3f1cd189089e16da04d1e4837d358a67aa3dab10ffbe"
+checksum = "119bc05b5b6bc3e7f5b67ce8b8080e185da94bd83c447f91b6b3f3ecf60cbab1"
dependencies = [
"unicode-properties",
"unicode-xid",
@@ -1540,9 +1540,9 @@ dependencies = [
[[package]]
name = "ra-ap-rustc_parse_format"
-version = "0.71.0"
+version = "0.73.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9234c96ffb0565286790407fb7eb7f55ebf69267de4db382fdec0a17f14b0e2"
+checksum = "70ed6150ae71d905c064dc88d7824ebb0fa81083f45d7477cba7b57176f2f635"
dependencies = [
"ra-ap-rustc_index",
"ra-ap-rustc_lexer",
@@ -1550,12 +1550,12 @@ dependencies = [
[[package]]
name = "ra-ap-rustc_pattern_analysis"
-version = "0.71.0"
+version = "0.73.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "273d5f72926a58c7eea27aebc898d1d5b32d23d2342f692a94a2cf8746aa4a2f"
+checksum = "6e830862a0ec85fce211d34735315686bb8d6a12d418d6d735fb534aa1cd3293"
dependencies = [
"ra-ap-rustc_index",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"rustc_apfloat",
"smallvec",
"tracing",
@@ -1640,7 +1640,7 @@ dependencies = [
"countme",
"hashbrown",
"memoffset",
- "rustc-hash",
+ "rustc-hash 1.1.0",
"text-size",
]
@@ -1680,7 +1680,7 @@ dependencies = [
"profile",
"project-model",
"rayon",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"scip",
"semver",
"serde",
@@ -1718,6 +1718,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
+name = "rustc-hash"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
+
+[[package]]
name = "rustc_apfloat"
version = "0.2.1+llvm-462a31f5a5ab"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1746,7 +1752,7 @@ dependencies = [
"oorandom",
"parking_lot",
"rand",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"salsa-macros",
"smallvec",
"tracing",
@@ -1898,7 +1904,7 @@ version = "0.0.0"
dependencies = [
"hashbrown",
"la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"salsa",
"stdx",
"syntax",
@@ -1967,7 +1973,7 @@ dependencies = [
"ra-ap-rustc_lexer",
"rayon",
"rowan",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"rustc_apfloat",
"smol_str",
"stdx",
@@ -1983,7 +1989,7 @@ version = "0.0.0"
dependencies = [
"intern",
"parser",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"span",
"stdx",
"syntax",
@@ -2000,7 +2006,7 @@ dependencies = [
"cfg",
"hir-expand",
"intern",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"span",
"stdx",
"test-utils",
@@ -2014,7 +2020,7 @@ dependencies = [
"dissimilar",
"paths",
"profile",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"stdx",
"text-size",
"tracing",
@@ -2361,7 +2367,7 @@ dependencies = [
"indexmap",
"nohash-hasher",
"paths",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"stdx",
"tracing",
]
@@ -2374,7 +2380,7 @@ dependencies = [
"notify",
"paths",
"rayon",
- "rustc-hash",
+ "rustc-hash 2.0.0",
"stdx",
"tracing",
"vfs",
diff --git a/Cargo.toml b/Cargo.toml
index 8c099f324b..9db62de9ab 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -85,18 +85,18 @@ tt = { path = "./crates/tt", version = "0.0.0" }
vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
vfs = { path = "./crates/vfs", version = "0.0.0" }
-ra-ap-rustc_lexer = { version = "0.71.0", default-features = false }
-ra-ap-rustc_parse_format = { version = "0.71.0", default-features = false }
-ra-ap-rustc_index = { version = "0.71.0", default-features = false }
-ra-ap-rustc_abi = { version = "0.71.0", default-features = false }
-ra-ap-rustc_pattern_analysis = { version = "0.71.0", default-features = false }
+ra-ap-rustc_lexer = { version = "0.73", default-features = false }
+ra-ap-rustc_parse_format = { version = "0.73", default-features = false }
+ra-ap-rustc_index = { version = "0.73", default-features = false }
+ra-ap-rustc_abi = { version = "0.73", default-features = false }
+ra-ap-rustc_pattern_analysis = { version = "0.73", default-features = false }
# local crates that aren't published to crates.io. These should not have versions.
test-fixture = { path = "./crates/test-fixture" }
test-utils = { path = "./crates/test-utils" }
# In-tree crates that are published separately and follow semver. See lib/README.md
-line-index = { version = "0.1.1" }
+line-index = { version = "0.1.2" }
la-arena = { version = "0.3.1" }
lsp-server = { version = "0.7.6" }
@@ -136,7 +136,7 @@ process-wrap = { version = "8.0.2", features = ["std"] }
pulldown-cmark-to-cmark = "10.0.4"
pulldown-cmark = { version = "0.9.0", default-features = false }
rayon = "1.8.0"
-rustc-hash = "1.1.0"
+rustc-hash = "2.0.0"
semver = "1.0.14"
serde = { version = "1.0.192", features = ["derive"] }
serde_json = "1.0.108"
diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs
index 3ecb57c756..263fad51d7 100644
--- a/crates/hir-def/src/data.rs
+++ b/crates/hir-def/src/data.rs
@@ -148,6 +148,10 @@ impl FunctionData {
self.flags.contains(FnFlags::HAS_UNSAFE_KW)
}
+ pub fn is_safe(&self) -> bool {
+ self.flags.contains(FnFlags::HAS_SAFE_KW)
+ }
+
pub fn is_varargs(&self) -> bool {
self.flags.contains(FnFlags::IS_VARARGS)
}
@@ -567,6 +571,8 @@ pub struct StaticData {
pub visibility: RawVisibility,
pub mutable: bool,
pub is_extern: bool,
+ pub has_safe_kw: bool,
+ pub has_unsafe_kw: bool,
}
impl StaticData {
@@ -581,6 +587,8 @@ impl StaticData {
visibility: item_tree[statik.visibility].clone(),
mutable: statik.mutable,
is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)),
+ has_safe_kw: statik.has_safe_kw,
+ has_unsafe_kw: statik.has_unsafe_kw,
})
}
}
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index f16230e1dc..7cb833fdce 100644
--- a/crates/hir-def/src/item_tree.rs
+++ b/crates/hir-def/src/item_tree.rs
@@ -754,6 +754,7 @@ bitflags::bitflags! {
const HAS_ASYNC_KW = 1 << 4;
const HAS_UNSAFE_KW = 1 << 5;
const IS_VARARGS = 1 << 6;
+ const HAS_SAFE_KW = 1 << 7;
}
}
@@ -822,7 +823,10 @@ pub struct Const {
pub struct Static {
pub name: Name,
pub visibility: RawVisibilityId,
+ // TODO: use bitflags when we have more flags
pub mutable: bool,
+ pub has_safe_kw: bool,
+ pub has_unsafe_kw: bool,
pub type_ref: Interned<TypeRef>,
pub ast_id: FileAstId<ast::Static>,
}
diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs
index 7aac383ab4..431a7f66f4 100644
--- a/crates/hir-def/src/item_tree/lower.rs
+++ b/crates/hir-def/src/item_tree/lower.rs
@@ -440,6 +440,9 @@ impl<'a> Ctx<'a> {
if func.unsafe_token().is_some() {
flags |= FnFlags::HAS_UNSAFE_KW;
}
+ if func.safe_token().is_some() {
+ flags |= FnFlags::HAS_SAFE_KW;
+ }
if has_var_args {
flags |= FnFlags::IS_VARARGS;
}
@@ -484,8 +487,11 @@ impl<'a> Ctx<'a> {
let type_ref = self.lower_type_ref_opt(static_.ty());
let visibility = self.lower_visibility(static_);
let mutable = static_.mut_token().is_some();
+ let has_safe_kw = static_.safe_token().is_some();
+ let has_unsafe_kw = static_.unsafe_token().is_some();
let ast_id = self.source_ast_id_map.ast_id(static_);
- let res = Static { name, visibility, mutable, type_ref, ast_id };
+ let res =
+ Static { name, visibility, mutable, type_ref, ast_id, has_safe_kw, has_unsafe_kw };
Some(id(self.data().statics.alloc(res)))
}
diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs
index b5a65abce8..9dce28b2e4 100644
--- a/crates/hir-def/src/item_tree/pretty.rs
+++ b/crates/hir-def/src/item_tree/pretty.rs
@@ -278,6 +278,9 @@ impl Printer<'_> {
if flags.contains(FnFlags::HAS_UNSAFE_KW) {
w!(self, "unsafe ");
}
+ if flags.contains(FnFlags::HAS_SAFE_KW) {
+ w!(self, "safe ");
+ }
if let Some(abi) = abi {
w!(self, "extern \"{}\" ", abi);
}
@@ -379,9 +382,23 @@ impl Printer<'_> {
wln!(self, " = _;");
}
ModItem::Static(it) => {
- let Static { name, visibility, mutable, type_ref, ast_id } = &self.tree[it];
+ let Static {
+ name,
+ visibility,
+ mutable,
+ type_ref,
+ ast_id,
+ has_safe_kw,
+ has_unsafe_kw,
+ } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility);
+ if *has_safe_kw {
+ w!(self, "safe ");
+ }
+ if *has_unsafe_kw {
+ w!(self, "unsafe ");
+ }
w!(self, "static ");
if *mutable {
w!(self, "mut ");
diff --git a/crates/hir-def/src/visibility.rs b/crates/hir-def/src/visibility.rs
index 11d91513f1..3aeb88047a 100644
--- a/crates/hir-def/src/visibility.rs
+++ b/crates/hir-def/src/visibility.rs
@@ -139,13 +139,11 @@ impl Visibility {
let def_map_block = def_map.block_id();
loop {
match (to_module.block, def_map_block) {
- // to_module is not a block, so there is no parent def map to use
+ // `to_module` is not a block, so there is no parent def map to use.
(None, _) => (),
+ // `to_module` is at `def_map`'s block, no need to move further.
(Some(a), Some(b)) if a == b => {
cov_mark::hit!(is_visible_from_same_block_def_map);
- if let Some(parent) = def_map.parent() {
- to_module = parent;
- }
}
_ => {
if let Some(parent) = to_module.def_map(db).parent() {
diff --git a/crates/hir-expand/src/builtin/fn_macro.rs b/crates/hir-expand/src/builtin/fn_macro.rs
index d04225b872..4894c7a931 100644
--- a/crates/hir-expand/src/builtin/fn_macro.rs
+++ b/crates/hir-expand/src/builtin/fn_macro.rs
@@ -5,19 +5,20 @@ use cfg::CfgExpr;
use either::Either;
use intern::{sym, Symbol};
use mbe::{expect_fragment, DelimiterKind};
-use span::{Edition, EditionedFileId, Span, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID};
+use span::{Edition, EditionedFileId, Span};
use stdx::format_to;
use syntax::{
format_smolstr,
unescape::{unescape_byte, unescape_char, unescape_unicode, Mode},
};
-use syntax_bridge::parse_to_token_tree;
+use syntax_bridge::syntax_node_to_token_tree;
use crate::{
builtin::quote::{dollar_crate, quote},
db::ExpandDatabase,
hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt},
name,
+ span_map::SpanMap,
tt::{self, DelimSpan},
ExpandError, ExpandResult, HirFileIdExt, Lookup as _, MacroCallId,
};
@@ -739,18 +740,14 @@ fn include_expand(
return ExpandResult::new(tt::Subtree::empty(DelimSpan { open: span, close: span }), e)
}
};
- match parse_to_token_tree(
- file_id.edition(),
- SpanAnchor { file_id, ast_id: ROOT_ERASED_FILE_AST_ID },
- SyntaxContextId::ROOT,
- &db.file_text(file_id.file_id()),
- ) {
- Some(it) => ExpandResult::ok(it),
- None => ExpandResult::new(
- tt::Subtree::empty(DelimSpan { open: span, close: span }),
- ExpandError::other(span, "failed to parse included file"),
- ),
- }
+ let span_map = db.real_span_map(file_id);
+ // FIXME: Parse errors
+ ExpandResult::ok(syntax_node_to_token_tree(
+ &db.parse(file_id).syntax_node(),
+ SpanMap::RealSpanMap(span_map),
+ span,
+ syntax_bridge::DocCommentDesugarMode::ProcMacro,
+ ))
}
pub fn include_input_to_file_id(
diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs
index d412bf4eee..0d19ae202c 100644
--- a/crates/hir-expand/src/db.rs
+++ b/crates/hir-expand/src/db.rs
@@ -35,7 +35,7 @@ type MacroArgResult = (Arc<tt::Subtree>, SyntaxFixupUndoInfo, Span);
/// an error will be emitted.
///
/// Actual max for `analysis-stats .` at some point: 30672.
-static TOKEN_LIMIT: Limit = Limit::new(1_048_576);
+static TOKEN_LIMIT: Limit = Limit::new(2_097_152);
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum TokenExpander {
diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs
index 7093fcadcb..0a8bfaa70f 100644
--- a/crates/hir-ty/src/consteval/tests.rs
+++ b/crates/hir-ty/src/consteval/tests.rs
@@ -95,7 +95,8 @@ fn check_answer(ra_fixture: &str, check: impl FnOnce(&[u8], &MemoryMap)) {
fn pretty_print_err(e: ConstEvalError, db: TestDB) -> String {
let mut err = String::new();
let span_formatter = |file, range| format!("{file:?} {range:?}");
- let edition = db.crate_graph()[db.test_crate()].edition;
+ let edition =
+ db.crate_graph()[*db.crate_graph().crates_in_topological_order().last().unwrap()].edition;
match e {
ConstEvalError::MirLowerError(e) => e.pretty_print(&mut err, &db, span_formatter, edition),
ConstEvalError::MirEvalError(e) => e.pretty_print(&mut err, &db, span_formatter, edition),
@@ -2896,7 +2897,7 @@ fn recursive_adt() {
{
const VARIANT_TAG_TREE: TagTree = TagTree::Choice(
&[
- TagTree::Leaf,
+ TAG_TREE,
],
);
VARIANT_TAG_TREE
@@ -2905,6 +2906,6 @@ fn recursive_adt() {
TAG_TREE
};
"#,
- |e| matches!(e, ConstEvalError::MirEvalError(MirEvalError::StackOverflow)),
+ |e| matches!(e, ConstEvalError::MirLowerError(MirLowerError::Loop)),
);
}
diff --git a/crates/hir-ty/src/diagnostics/unsafe_check.rs b/crates/hir-ty/src/diagnostics/unsafe_check.rs
index ff45c725c7..bcfc37c867 100644
--- a/crates/hir-ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir-ty/src/diagnostics/unsafe_check.rs
@@ -89,7 +89,7 @@ fn walk_unsafe(
let value_or_partial = resolver.resolve_path_in_value_ns(db.upcast(), path);
if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id), _)) = value_or_partial {
let static_data = db.static_data(id);
- if static_data.mutable || static_data.is_extern {
+ if static_data.mutable || (static_data.is_extern && !static_data.has_safe_kw) {
unsafe_expr_cb(UnsafeExpr { expr: current, inside_unsafe_block });
}
}
diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs
index 7300453ff0..e4881d7520 100644
--- a/crates/hir-ty/src/infer/unify.rs
+++ b/crates/hir-ty/src/infer/unify.rs
@@ -917,9 +917,19 @@ impl<'a> InferenceTable<'a> {
/// Check if given type is `Sized` or not
pub(crate) fn is_sized(&mut self, ty: &Ty) -> bool {
// Early return for some obvious types
- if matches!(ty.kind(Interner), TyKind::Scalar(..) | TyKind::Ref(..) | TyKind::Raw(..)) {
+ if matches!(
+ ty.kind(Interner),
+ TyKind::Scalar(..)
+ | TyKind::Ref(..)
+ | TyKind::Raw(..)
+ | TyKind::Never
+ | TyKind::FnDef(..)
+ | TyKind::Array(..)
+ | TyKind::Function(_)
+ ) {
return true;
}
+
if let Some((AdtId::StructId(id), subst)) = ty.as_adt() {
let struct_data = self.db.struct_data(id);
if let Some((last_field, _)) = struct_data.variant_data.fields().iter().last() {
diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs
index 2c68d50013..8083144072 100644
--- a/crates/hir-ty/src/layout.rs
+++ b/crates/hir-ty/src/layout.rs
@@ -72,18 +72,15 @@ pub type Variants = hir_def::layout::Variants<RustcFieldIdx, RustcEnumVariantIdx
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum LayoutError {
- // FIXME: Remove variants that duplicate LayoutCalculatorError's variants after sync
+ // FIXME: Remove more variants once they get added to LayoutCalculatorError
BadCalc(LayoutCalculatorError<()>),
- EmptyUnion,
HasErrorConst,
HasErrorType,
HasPlaceholder,
InvalidSimdType,
NotImplemented,
RecursiveTypeWithoutIndirection,
- SizeOverflow,
TargetLayoutNotAvailable,
- UnexpectedUnsized,
Unknown,
UserReprTooSmall,
}
@@ -93,7 +90,6 @@ impl fmt::Display for LayoutError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
LayoutError::BadCalc(err) => err.fallback_fmt(f),
- LayoutError::EmptyUnion => write!(f, "type is an union with no fields"),
LayoutError::HasErrorConst => write!(f, "type contains an unevaluatable const"),
LayoutError::HasErrorType => write!(f, "type contains an error"),
LayoutError::HasPlaceholder => write!(f, "type contains placeholders"),
@@ -102,11 +98,7 @@ impl fmt::Display for LayoutError {
LayoutError::RecursiveTypeWithoutIndirection => {
write!(f, "recursive type without indirection")
}
- LayoutError::SizeOverflow => write!(f, "size overflow"),
LayoutError::TargetLayoutNotAvailable => write!(f, "target layout not available"),
- LayoutError::UnexpectedUnsized => {
- write!(f, "an unsized type was found where a sized type was expected")
- }
LayoutError::Unknown => write!(f, "unknown"),
LayoutError::UserReprTooSmall => {
write!(f, "the `#[repr]` hint is too small to hold the discriminants of the enum")
@@ -181,7 +173,10 @@ fn layout_of_simd_ty(
};
// Compute the size and alignment of the vector:
- let size = e_ly.size.checked_mul(e_len, dl).ok_or(LayoutError::SizeOverflow)?;
+ let size = e_ly
+ .size
+ .checked_mul(e_len, dl)
+ .ok_or(LayoutError::BadCalc(LayoutCalculatorError::SizeOverflow))?;
let align = dl.vector_align(size);
let size = size.align_to(align.abi);
@@ -294,7 +289,10 @@ pub fn layout_of_ty_query(
TyKind::Array(element, count) => {
let count = try_const_usize(db, count).ok_or(LayoutError::HasErrorConst)? as u64;
let element = db.layout_of_ty(element.clone(), trait_env)?;
- let size = element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow)?;
+ let size = element
+ .size
+ .checked_mul(count, dl)
+ .ok_or(LayoutError::BadCalc(LayoutCalculatorError::SizeOverflow))?;
let abi = if count != 0 && matches!(element.abi, Abi::Uninhabited) {
Abi::Uninhabited
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index 649cf88bb8..9c1d8bcf36 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -51,10 +51,7 @@ mod test_db;
#[cfg(test)]
mod tests;
-use std::{
- collections::hash_map::Entry,
- hash::{BuildHasherDefault, Hash},
-};
+use std::hash::Hash;
use base_db::ra_salsa::InternValueTrivial;
use chalk_ir::{
@@ -65,10 +62,11 @@ use chalk_ir::{
use either::Either;
use hir_def::{hir::ExprId, type_ref::Rawness, CallableDefId, GeneralConstId, TypeOrConstParamId};
use hir_expand::name::Name;
+use indexmap::{map::Entry, IndexMap};
use intern::{sym, Symbol};
use la_arena::{Arena, Idx};
use mir::{MirEvalError, VTableMap};
-use rustc_hash::{FxHashMap, FxHashSet};
+use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet};
use span::Edition;
use syntax::ast::{make, ConstArg};
use traits::FnTrait;
@@ -199,7 +197,7 @@ pub enum MemoryMap {
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct ComplexMemoryMap {
- memory: FxHashMap<usize, Box<[u8]>>,
+ memory: IndexMap<usize, Box<[u8]>, FxBuildHasher>,
vtable: VTableMap,
}
@@ -245,7 +243,7 @@ impl MemoryMap {
match self {
MemoryMap::Empty => Ok(Default::default()),
MemoryMap::Simple(m) => transform((&0, m)).map(|(addr, val)| {
- let mut map = FxHashMap::with_capacity_and_hasher(1, BuildHasherDefault::default());
+ let mut map = FxHashMap::with_capacity_and_hasher(1, rustc_hash::FxBuildHasher);
map.insert(addr, val);
map
}),
diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs
index d1ce68da6d..620bba2d75 100644
--- a/crates/hir-ty/src/utils.rs
+++ b/crates/hir-ty/src/utils.rs
@@ -257,10 +257,12 @@ pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
return true;
}
- match func.lookup(db.upcast()).container {
+ let loc = func.lookup(db.upcast());
+ match loc.container {
hir_def::ItemContainerId::ExternBlockId(block) => {
- // Function in an `extern` block are always unsafe to call, except when it has
- // `"rust-intrinsic"` ABI there are a few exceptions.
+ // Function in an `extern` block are always unsafe to call, except when
+ // it is marked as `safe` or it has `"rust-intrinsic"` ABI there are a
+ // few exceptions.
let id = block.lookup(db.upcast()).id;
let is_intrinsic =
@@ -270,8 +272,8 @@ pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
// Intrinsics are unsafe unless they have the rustc_safe_intrinsic attribute
!data.attrs.by_key(&sym::rustc_safe_intrinsic).exists()
} else {
- // Extern items are always unsafe
- true
+ // Extern items without `safe` modifier are always unsafe
+ !data.is_safe()
}
}
_ => false,
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index b27f1fbb5d..3eac33ce99 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -892,29 +892,8 @@ impl<'db> SemanticsImpl<'db> {
f: &mut dyn FnMut(InFile<SyntaxToken>, SyntaxContextId) -> ControlFlow<T>,
) -> Option<T> {
let _p = tracing::info_span!("descend_into_macros_impl").entered();
- let (sa, span, file_id) = token
- .parent()
- .and_then(|parent| {
- self.analyze_impl(InRealFile::new(file_id, &parent).into(), None, false)
- })
- .and_then(|sa| {
- let file_id = sa.file_id.file_id()?;
- Some((
- sa,
- self.db.real_span_map(file_id).span_for_range(token.text_range()),
- HirFileId::from(file_id),
- ))
- })?;
- let mut m_cache = self.macro_call_cache.borrow_mut();
- let def_map = sa.resolver.def_map();
-
- // A stack of tokens to process, along with the file they came from
- // These are tracked to know which macro calls we still have to look into
- // the tokens themselves aren't that interesting as the span that is being used to map
- // things down never changes.
- let mut stack: Vec<(_, SmallVec<[_; 2]>)> =
- vec![(file_id, smallvec![(token, SyntaxContextId::ROOT)])];
+ let span = self.db.real_span_map(file_id).span_for_range(token.text_range());
// Process the expansion of a call, pushing all tokens with our span in the expansion back onto our stack
let process_expansion_for_token = |stack: &mut Vec<_>, macro_file| {
@@ -926,7 +905,6 @@ impl<'db> SemanticsImpl<'db> {
.map(SmallVec::<[_; 2]>::from_iter),
)
})?;
-
// we have found a mapping for the token if the vec is non-empty
let res = mapped_tokens.is_empty().not().then_some(());
// requeue the tokens we got from mapping our current token down
@@ -934,6 +912,33 @@ impl<'db> SemanticsImpl<'db> {
res
};
+ // A stack of tokens to process, along with the file they came from
+ // These are tracked to know which macro calls we still have to look into
+ // the tokens themselves aren't that interesting as the span that is being used to map
+ // things down never changes.
+ let mut stack: Vec<(_, SmallVec<[_; 2]>)> = vec![];
+ let include = self.s2d_cache.borrow_mut().get_or_insert_include_for(self.db, file_id);
+ match include {
+ Some(include) => {
+ // include! inputs are always from real files, so they only need to be handled once upfront
+ process_expansion_for_token(&mut stack, include)?;
+ }
+ None => {
+ stack.push((file_id.into(), smallvec![(token, SyntaxContextId::ROOT)]));
+ }
+ }
+
+ let (file_id, tokens) = stack.first()?;
+ // make sure we pick the token in the expanded include if we encountered an include,
+ // otherwise we'll get the wrong semantics
+ let sa =
+ tokens.first()?.0.parent().and_then(|parent| {
+ self.analyze_impl(InFile::new(*file_id, &parent), None, false)
+ })?;
+
+ let mut m_cache = self.macro_call_cache.borrow_mut();
+ let def_map = sa.resolver.def_map();
+
// Filters out all tokens that contain the given range (usually the macro call), any such
// token is redundant as the corresponding macro call has already been processed
let filter_duplicates = |tokens: &mut SmallVec<_>, range: TextRange| {
@@ -1011,6 +1016,7 @@ impl<'db> SemanticsImpl<'db> {
) {
call.as_macro_file()
} else {
+ // FIXME: This is wrong, the SourceAnalyzer might be invalid here
sa.expand(self.db, mcall.as_ref())?
};
m_cache.insert(mcall, it);
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs
index fd6d52d6c9..389778b44e 100644
--- a/crates/hir/src/semantics/source_to_def.rs
+++ b/crates/hir/src/semantics/source_to_def.rs
@@ -104,7 +104,7 @@ use hir_expand::{
};
use rustc_hash::FxHashMap;
use smallvec::SmallVec;
-use span::{FileId, MacroFileId};
+use span::{EditionedFileId, FileId, MacroFileId};
use stdx::impl_from;
use syntax::{
ast::{self, HasName},
@@ -118,9 +118,27 @@ pub(super) struct SourceToDefCache {
pub(super) dynmap_cache: FxHashMap<(ChildContainer, HirFileId), DynMap>,
expansion_info_cache: FxHashMap<MacroFileId, ExpansionInfo>,
pub(super) file_to_def_cache: FxHashMap<FileId, SmallVec<[ModuleId; 1]>>,
+ pub(super) included_file_cache: FxHashMap<EditionedFileId, Option<MacroFileId>>,
}
impl SourceToDefCache {
+ pub(super) fn get_or_insert_include_for(
+ &mut self,
+ db: &dyn HirDatabase,
+ file: EditionedFileId,
+ ) -> Option<MacroFileId> {
+ if let Some(&m) = self.included_file_cache.get(&file) {
+ return m;
+ }
+ self.included_file_cache.insert(file, None);
+ for &crate_id in db.relevant_crates(file.into()).iter() {
+ db.include_macro_invoc(crate_id).iter().for_each(|&(macro_call_id, file_id)| {
+ self.included_file_cache.insert(file_id, Some(MacroFileId { macro_call_id }));
+ });
+ }
+ self.included_file_cache.get(&file).copied().flatten()
+ }
+
pub(super) fn get_or_insert_expansion(
&mut self,
sema: &SemanticsImpl<'_>,
@@ -163,9 +181,13 @@ impl SourceToDefCtx<'_, '_> {
.include_macro_invoc(crate_id)
.iter()
.filter(|&&(_, file_id)| file_id == file)
- .flat_map(|(call, _)| {
+ .flat_map(|&(macro_call_id, file_id)| {
+ self.cache
+ .included_file_cache
+ .insert(file_id, Some(MacroFileId { macro_call_id }));
modules(
- call.lookup(self.db.upcast())
+ macro_call_id
+ .lookup(self.db.upcast())
.kind
.file_id()
.original_file(self.db.upcast())
diff --git a/crates/ide-assists/src/handlers/bool_to_enum.rs b/crates/ide-assists/src/handlers/bool_to_enum.rs
index cd5fe0f862..c035c59ffc 100644
--- a/crates/ide-assists/src/handlers/bool_to_enum.rs
+++ b/crates/ide-assists/src/handlers/bool_to_enum.rs
@@ -1095,6 +1095,7 @@ fn main() {
#[test]
fn field_enum_cross_file() {
+ // FIXME: The import is missing
check_assist(
bool_to_enum,
r#"
@@ -1132,7 +1133,7 @@ fn foo() {
}
//- /main.rs
-use foo::{Bool, Foo};
+use foo::Foo;
mod foo;
diff --git a/crates/ide-assists/src/handlers/unwrap_result_return_type.rs b/crates/ide-assists/src/handlers/unwrap_result_return_type.rs
deleted file mode 100644
index a1987247cb..0000000000
--- a/crates/ide-assists/src/handlers/unwrap_result_return_type.rs
+++ /dev/null
@@ -1,1115 +0,0 @@
-use ide_db::{
- famous_defs::FamousDefs,
- syntax_helpers::node_ext::{for_each_tail_expr, walk_expr},
-};
-use itertools::Itertools;
-use syntax::{
- ast::{self, Expr, HasGenericArgs},
- match_ast, AstNode, NodeOrToken, SyntaxKind, TextRange,
-};
-
-use crate::{AssistContext, AssistId, AssistKind, Assists};
-
-// Assist: unwrap_result_return_type
-//
-// Unwrap the function's return type.
-//
-// ```
-// # //- minicore: result
-// fn foo() -> Result<i32>$0 { Ok(42i32) }
-// ```
-// ->
-// ```
-// fn foo() -> i32 { 42i32 }
-// ```
-pub(crate) fn unwrap_result_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
- let ret_type = ctx.find_node_at_offset::<ast::RetType>()?;
- let parent = ret_type.syntax().parent()?;
- let body = match_ast! {
- match parent {
- ast::Fn(func) => func.body()?,
- ast::ClosureExpr(closure) => match closure.body()? {
- Expr::BlockExpr(block) => block,
- // closures require a block when a return type is specified
- _ => return None,
- },
- _ => return None,
- }
- };
-
- let type_ref = &ret_type.ty()?;
- let Some(hir::Adt::Enum(ret_enum)) = ctx.sema.resolve_type(type_ref)?.as_adt() else {
- return None;
- };
- let result_enum =
- FamousDefs(&ctx.sema, ctx.sema.scope(type_ref.syntax())?.krate()).core_result_Result()?;
- if ret_enum != result_enum {
- return None;
- }
-
- let ok_type = unwrap_result_type(type_ref)?;
-
- acc.add(
- AssistId("unwrap_result_return_type", AssistKind::RefactorRewrite),
- "Unwrap Result return type",
- type_ref.syntax().text_range(),
- |builder| {
- let body = ast::Expr::BlockExpr(body);
-
- let mut exprs_to_unwrap = Vec::new();
- let tail_cb = &mut |e: &_| tail_cb_impl(&mut exprs_to_unwrap, e);
- walk_expr(&body, &mut |expr| {
- if let Expr::ReturnExpr(ret_expr) = expr {
- if let Some(ret_expr_arg) = &ret_expr.expr() {
- for_each_tail_expr(ret_expr_arg, tail_cb);
- }
- }
- });
- for_each_tail_expr(&body, tail_cb);
-
- let is_unit_type = is_unit_type(&ok_type);
- if is_unit_type {
- let mut text_range = ret_type.syntax().text_range();
-
- if let Some(NodeOrToken::Token(token)) = ret_type.syntax().next_sibling_or_token() {
- if token.kind() == SyntaxKind::WHITESPACE {
- text_range = TextRange::new(text_range.start(), token.text_range().end());
- }
- }
-
- builder.delete(text_range);
- } else {
- builder.replace(type_ref.syntax().text_range(), ok_type.syntax().text());
- }
-
- for ret_expr_arg in exprs_to_unwrap {
- let ret_expr_str = ret_expr_arg.to_string();
- if ret_expr_str.starts_with("Ok(") || ret_expr_str.starts_with("Err(") {
- let arg_list = ret_expr_arg.syntax().children().find_map(ast::ArgList::cast);
- if let Some(arg_list) = arg_list {
- if is_unit_type {
- match ret_expr_arg.syntax().prev_sibling_or_token() {
- // Useful to delete the entire line without leaving trailing whitespaces
- Some(whitespace) => {
- let new_range = TextRange::new(
- whitespace.text_range().start(),
- ret_expr_arg.syntax().text_range().end(),
- );
- builder.delete(new_range);
- }
- None => {
- builder.delete(ret_expr_arg.syntax().text_range());
- }
- }
- } else {
- builder.replace(
- ret_expr_arg.syntax().text_range(),
- arg_list.args().join(", "),
- );
- }
- }
- }
- }
- },
- )
-}
-
-fn tail_cb_impl(acc: &mut Vec<ast::Expr>, e: &ast::Expr) {
- match e {
- Expr::BreakExpr(break_expr) => {
- if let Some(break_expr_arg) = break_expr.expr() {
- for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(acc, e))
- }
- }
- Expr::ReturnExpr(_) => {
- // all return expressions have already been handled by the walk loop
- }
- e => acc.push(e.clone()),
- }
-}
-
-// Tries to extract `T` from `Result<T, E>`.
-fn unwrap_result_type(ty: &ast::Type) -> Option<ast::Type> {
- let ast::Type::PathType(path_ty) = ty else {
- return None;
- };
- let path = path_ty.path()?;
- let segment = path.first_segment()?;
- let generic_arg_list = segment.generic_arg_list()?;
- let generic_args: Vec<_> = generic_arg_list.generic_args().collect();
- let ast::GenericArg::TypeArg(ok_type) = generic_args.first()? else {
- return None;
- };
- ok_type.ty()
-}
-
-fn is_unit_type(ty: &ast::Type) -> bool {
- let ast::Type::TupleType(tuple) = ty else { return false };
- tuple.fields().next().is_none()
-}
-
-#[cfg(test)]
-mod tests {
- use crate::tests::{check_assist, check_assist_not_applicable};
-
- use super::*;
-
- #[test]
- fn unwrap_result_return_type_simple() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() -> Result<i3$02> {
- let test = "test";
- return Ok(42i32);
-}
-"#,
- r#"
-fn foo() -> i32 {
- let test = "test";
- return 42i32;
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_unit_type() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() -> Result<(), Box<dyn Error$0>> {
- Ok(())
-}
-"#,
- r#"
-fn foo() {
-}
-"#,
- );
-
- // Unformatted return type
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() -> Result<(), Box<dyn Error$0>>{
- Ok(())
-}
-"#,
- r#"
-fn foo() {
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_ending_with_parent() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() -> Result<i32, Box<dyn Error$0>> {
- if true {
- Ok(42)
- } else {
- foo()
- }
-}
-"#,
- r#"
-fn foo() -> i32 {
- if true {
- 42
- } else {
- foo()
- }
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_return_type_break_split_tail() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() -> Result<i3$02, String> {
- loop {
- break if true {
- Ok(1)
- } else {
- Ok(0)
- };
- }
-}
-"#,
- r#"
-fn foo() -> i32 {
- loop {
- break if true {
- 1
- } else {
- 0
- };
- }
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_closure() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() {
- || -> Result<i32$0> {
- let test = "test";
- return Ok(42i32);
- };
-}
-"#,
- r#"
-fn foo() {
- || -> i32 {
- let test = "test";
- return 42i32;
- };
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_return_type_bad_cursor() {
- check_assist_not_applicable(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() -> i32 {
- let test = "test";$0
- return 42i32;
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_return_type_bad_cursor_closure() {
- check_assist_not_applicable(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() {
- || -> i32 {
- let test = "test";$0
- return 42i32;
- };
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_closure_non_block() {
- check_assist_not_applicable(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() { || -> i$032 3; }
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_return_type_already_not_result_std() {
- check_assist_not_applicable(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() -> i32$0 {
- let test = "test";
- return 42i32;
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_return_type_already_not_result_closure() {
- check_assist_not_applicable(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() {
- || -> i32$0 {
- let test = "test";
- return 42i32;
- };
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_with_tail() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() ->$0 Result<i32> {
- let test = "test";
- Ok(42i32)
-}
-"#,
- r#"
-fn foo() -> i32 {
- let test = "test";
- 42i32
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_with_tail_closure() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() {
- || ->$0 Result<i32, String> {
- let test = "test";
- Ok(42i32)
- };
-}
-"#,
- r#"
-fn foo() {
- || -> i32 {
- let test = "test";
- 42i32
- };
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_with_tail_only() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() -> Result<i32$0> { Ok(42i32) }
-"#,
- r#"
-fn foo() -> i32 { 42i32 }
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_with_tail_block_like() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() -> Result<i32>$0 {
- if true {
- Ok(42i32)
- } else {
- Ok(24i32)
- }
-}
-"#,
- r#"
-fn foo() -> i32 {
- if true {
- 42i32
- } else {
- 24i32
- }
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_without_block_closure() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() {
- || -> Result<i32, String>$0 {
- if true {
- Ok(42i32)
- } else {
- Ok(24i32)
- }
- };
-}
-"#,
- r#"
-fn foo() {
- || -> i32 {
- if true {
- 42i32
- } else {
- 24i32
- }
- };
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_with_nested_if() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() -> Result<i32>$0 {
- if true {
- if false {
- Ok(1)
- } else {
- Ok(2)
- }
- } else {
- Ok(24i32)
- }
-}
-"#,
- r#"
-fn foo() -> i32 {
- if true {
- if false {
- 1
- } else {
- 2
- }
- } else {
- 24i32
- }
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_with_await() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-async fn foo() -> Result<i$032> {
- if true {
- if false {
- Ok(1.await)
- } else {
- Ok(2.await)
- }
- } else {
- Ok(24i32.await)
- }
-}
-"#,
- r#"
-async fn foo() -> i32 {
- if true {
- if false {
- 1.await
- } else {
- 2.await
- }
- } else {
- 24i32.await
- }
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_with_array() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() -> Result<[i32; 3]$0> { Ok([1, 2, 3]) }
-"#,
- r#"
-fn foo() -> [i32; 3] { [1, 2, 3] }
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_with_cast() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() -$0> Result<i32> {
- if true {
- if false {
- Ok(1 as i32)
- } else {
- Ok(2 as i32)
- }
- } else {
- Ok(24 as i32)
- }
-}
-"#,
- r#"
-fn foo() -> i32 {
- if true {
- if false {
- 1 as i32
- } else {
- 2 as i32
- }
- } else {
- 24 as i32
- }
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_with_tail_block_like_match() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() -> Result<i32$0> {
- let my_var = 5;
- match my_var {
- 5 => Ok(42i32),
- _ => Ok(24i32),
- }
-}
-"#,
- r#"
-fn foo() -> i32 {
- let my_var = 5;
- match my_var {
- 5 => 42i32,
- _ => 24i32,
- }
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_with_loop_with_tail() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() -> Result<i32$0> {
- let my_var = 5;
- loop {
- println!("test");
- 5
- }
- Ok(my_var)
-}
-"#,
- r#"
-fn foo() -> i32 {
- let my_var = 5;
- loop {
- println!("test");
- 5
- }
- my_var
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_with_loop_in_let_stmt() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() -> Result<i32$0> {
- let my_var = let x = loop {
- break 1;
- };
- Ok(my_var)
-}
-"#,
- r#"
-fn foo() -> i32 {
- let my_var = let x = loop {
- break 1;
- };
- my_var
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_with_tail_block_like_match_return_expr() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() -> Result<i32>$0 {
- let my_var = 5;
- let res = match my_var {
- 5 => 42i32,
- _ => return Ok(24i32),
- };
- Ok(res)
-}
-"#,
- r#"
-fn foo() -> i32 {
- let my_var = 5;
- let res = match my_var {
- 5 => 42i32,
- _ => return 24i32,
- };
- res
-}
-"#,
- );
-
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() -> Result<i32$0> {
- let my_var = 5;
- let res = if my_var == 5 {
- 42i32
- } else {
- return Ok(24i32);
- };
- Ok(res)
-}
-"#,
- r#"
-fn foo() -> i32 {
- let my_var = 5;
- let res = if my_var == 5 {
- 42i32
- } else {
- return 24i32;
- };
- res
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_with_tail_block_like_match_deeper() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() -> Result<i32$0> {
- let my_var = 5;
- match my_var {
- 5 => {
- if true {
- Ok(42i32)
- } else {
- Ok(25i32)
- }
- },
- _ => {
- let test = "test";
- if test == "test" {
- return Ok(bar());
- }
- Ok(53i32)
- },
- }
-}
-"#,
- r#"
-fn foo() -> i32 {
- let my_var = 5;
- match my_var {
- 5 => {
- if true {
- 42i32
- } else {
- 25i32
- }
- },
- _ => {
- let test = "test";
- if test == "test" {
- return bar();
- }
- 53i32
- },
- }
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_with_tail_block_like_early_return() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() -> Result<i32$0> {
- let test = "test";
- if test == "test" {
- return Ok(24i32);
- }
- Ok(53i32)
-}
-"#,
- r#"
-fn foo() -> i32 {
- let test = "test";
- if test == "test" {
- return 24i32;
- }
- 53i32
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_in_tail_position() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo(num: i32) -> $0Result<i32, String> {
- return Ok(num)
-}
-"#,
- r#"
-fn foo(num: i32) -> i32 {
- return num
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_with_closure() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo(the_field: u32) -> Result<u32$0> {
- let true_closure = || { return true; };
- if the_field < 5 {
- let mut i = 0;
- if true_closure() {
- return Ok(99);
- } else {
- return Ok(0);
- }
- }
- Ok(the_field)
-}
-"#,
- r#"
-fn foo(the_field: u32) -> u32 {
- let true_closure = || { return true; };
- if the_field < 5 {
- let mut i = 0;
- if true_closure() {
- return 99;
- } else {
- return 0;
- }
- }
- the_field
-}
-"#,
- );
-
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo(the_field: u32) -> Result<u32$0> {
- let true_closure = || {
- return true;
- };
- if the_field < 5 {
- let mut i = 0;
-
-
- if true_closure() {
- return Ok(99);
- } else {
- return Ok(0);
- }
- }
- let t = None;
-
- Ok(t.unwrap_or_else(|| the_field))
-}
-"#,
- r#"
-fn foo(the_field: u32) -> u32 {
- let true_closure = || {
- return true;
- };
- if the_field < 5 {
- let mut i = 0;
-
-
- if true_closure() {
- return 99;
- } else {
- return 0;
- }
- }
- let t = None;
-
- t.unwrap_or_else(|| the_field)
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_simple_with_weird_forms() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo() -> Result<i32$0> {
- let test = "test";
- if test == "test" {
- return Ok(24i32);
- }
- let mut i = 0;
- loop {
- if i == 1 {
- break Ok(55);
- }
- i += 1;
- }
-}
-"#,
- r#"
-fn foo() -> i32 {
- let test = "test";
- if test == "test" {
- return 24i32;
- }
- let mut i = 0;
- loop {
- if i == 1 {
- break 55;
- }
- i += 1;
- }
-}
-"#,
- );
-
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo(the_field: u32) -> Result<u32$0> {
- if the_field < 5 {
- let mut i = 0;
- loop {
- if i > 5 {
- return Ok(55u32);
- }
- i += 3;
- }
- match i {
- 5 => return Ok(99),
- _ => return Ok(0),
- };
- }
- Ok(the_field)
-}
-"#,
- r#"
-fn foo(the_field: u32) -> u32 {
- if the_field < 5 {
- let mut i = 0;
- loop {
- if i > 5 {
- return 55u32;
- }
- i += 3;
- }
- match i {
- 5 => return 99,
- _ => return 0,
- };
- }
- the_field
-}
-"#,
- );
-
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo(the_field: u32) -> Result<u32$0> {
- if the_field < 5 {
- let mut i = 0;
- match i {
- 5 => return Ok(99),
- _ => return Ok(0),
- }
- }
- Ok(the_field)
-}
-"#,
- r#"
-fn foo(the_field: u32) -> u32 {
- if the_field < 5 {
- let mut i = 0;
- match i {
- 5 => return 99,
- _ => return 0,
- }
- }
- the_field
-}
-"#,
- );
-
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo(the_field: u32) -> Result<u32$0> {
- if the_field < 5 {
- let mut i = 0;
- if i == 5 {
- return Ok(99)
- } else {
- return Ok(0)
- }
- }
- Ok(the_field)
-}
-"#,
- r#"
-fn foo(the_field: u32) -> u32 {
- if the_field < 5 {
- let mut i = 0;
- if i == 5 {
- return 99
- } else {
- return 0
- }
- }
- the_field
-}
-"#,
- );
-
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result
-fn foo(the_field: u32) -> Result<u3$02> {
- if the_field < 5 {
- let mut i = 0;
- if i == 5 {
- return Ok(99);
- } else {
- return Ok(0);
- }
- }
- Ok(the_field)
-}
-"#,
- r#"
-fn foo(the_field: u32) -> u32 {
- if the_field < 5 {
- let mut i = 0;
- if i == 5 {
- return 99;
- } else {
- return 0;
- }
- }
- the_field
-}
-"#,
- );
- }
-
- #[test]
- fn unwrap_result_return_type_nested_type() {
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result, option
-fn foo() -> Result<Option<i32$0>, ()> {
- Ok(Some(42))
-}
-"#,
- r#"
-fn foo() -> Option<i32> {
- Some(42)
-}
-"#,
- );
-
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result, option
-fn foo() -> Result<Option<Result<i32$0, ()>>, ()> {
- Ok(None)
-}
-"#,
- r#"
-fn foo() -> Option<Result<i32, ()>> {
- None
-}
-"#,
- );
-
- check_assist(
- unwrap_result_return_type,
- r#"
-//- minicore: result, option, iterators
-fn foo() -> Result<impl Iterator<Item = i32>$0, ()> {
- Ok(Some(42).into_iter())
-}
-"#,
- r#"
-fn foo() -> impl Iterator<Item = i32> {
- Some(42).into_iter()
-}
-"#,
- );
- }
-}
diff --git a/crates/ide-assists/src/handlers/unwrap_return_type.rs b/crates/ide-assists/src/handlers/unwrap_return_type.rs
new file mode 100644
index 0000000000..64d5e2c9b8
--- /dev/null
+++ b/crates/ide-assists/src/handlers/unwrap_return_type.rs
@@ -0,0 +1,2229 @@
+use ide_db::{
+ famous_defs::FamousDefs,
+ syntax_helpers::node_ext::{for_each_tail_expr, walk_expr},
+};
+use itertools::Itertools;
+use syntax::{
+ ast::{self, Expr, HasGenericArgs},
+ match_ast, AstNode, NodeOrToken, SyntaxKind, TextRange,
+};
+
+use crate::{AssistContext, AssistId, AssistKind, Assists};
+
+// Assist: unwrap_option_return_type
+//
+// Unwrap the function's return type.
+//
+// ```
+// # //- minicore: option
+// fn foo() -> Option<i32>$0 { Some(42i32) }
+// ```
+// ->
+// ```
+// fn foo() -> i32 { 42i32 }
+// ```
+
+// Assist: unwrap_result_return_type
+//
+// Unwrap the function's return type.
+//
+// ```
+// # //- minicore: result
+// fn foo() -> Result<i32>$0 { Ok(42i32) }
+// ```
+// ->
+// ```
+// fn foo() -> i32 { 42i32 }
+// ```
+
+pub(crate) fn unwrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
+ let ret_type = ctx.find_node_at_offset::<ast::RetType>()?;
+ let parent = ret_type.syntax().parent()?;
+ let body = match_ast! {
+ match parent {
+ ast::Fn(func) => func.body()?,
+ ast::ClosureExpr(closure) => match closure.body()? {
+ Expr::BlockExpr(block) => block,
+ // closures require a block when a return type is specified
+ _ => return None,
+ },
+ _ => return None,
+ }
+ };
+
+ let type_ref = &ret_type.ty()?;
+ let Some(hir::Adt::Enum(ret_enum)) = ctx.sema.resolve_type(type_ref)?.as_adt() else {
+ return None;
+ };
+
+ let famous_defs = FamousDefs(&ctx.sema, ctx.sema.scope(type_ref.syntax())?.krate());
+
+ let kind = UnwrapperKind::ALL
+ .iter()
+ .find(|k| matches!(k.core_type(&famous_defs), Some(core_type) if ret_enum == core_type))?;
+
+ let happy_type = extract_wrapped_type(type_ref)?;
+
+ acc.add(kind.assist_id(), kind.label(), type_ref.syntax().text_range(), |builder| {
+ let body = ast::Expr::BlockExpr(body);
+
+ let mut exprs_to_unwrap = Vec::new();
+ let tail_cb = &mut |e: &_| tail_cb_impl(&mut exprs_to_unwrap, e);
+ walk_expr(&body, &mut |expr| {
+ if let Expr::ReturnExpr(ret_expr) = expr {
+ if let Some(ret_expr_arg) = &ret_expr.expr() {
+ for_each_tail_expr(ret_expr_arg, tail_cb);
+ }
+ }
+ });
+ for_each_tail_expr(&body, tail_cb);
+
+ let is_unit_type = is_unit_type(&happy_type);
+ if is_unit_type {
+ let mut text_range = ret_type.syntax().text_range();
+
+ if let Some(NodeOrToken::Token(token)) = ret_type.syntax().next_sibling_or_token() {
+ if token.kind() == SyntaxKind::WHITESPACE {
+ text_range = TextRange::new(text_range.start(), token.text_range().end());
+ }
+ }
+
+ builder.delete(text_range);
+ } else {
+ builder.replace(type_ref.syntax().text_range(), happy_type.syntax().text());
+ }
+
+ for ret_expr_arg in exprs_to_unwrap {
+ let ret_expr_str = ret_expr_arg.to_string();
+
+ let needs_replacing = match kind {
+ UnwrapperKind::Option => ret_expr_str.starts_with("Some("),
+ UnwrapperKind::Result => {
+ ret_expr_str.starts_with("Ok(") || ret_expr_str.starts_with("Err(")
+ }
+ };
+
+ if needs_replacing {
+ let arg_list = ret_expr_arg.syntax().children().find_map(ast::ArgList::cast);
+ if let Some(arg_list) = arg_list {
+ if is_unit_type {
+ match ret_expr_arg.syntax().prev_sibling_or_token() {
+ // Useful to delete the entire line without leaving trailing whitespaces
+ Some(whitespace) => {
+ let new_range = TextRange::new(
+ whitespace.text_range().start(),
+ ret_expr_arg.syntax().text_range().end(),
+ );
+ builder.delete(new_range);
+ }
+ None => {
+ builder.delete(ret_expr_arg.syntax().text_range());
+ }
+ }
+ } else {
+ builder.replace(
+ ret_expr_arg.syntax().text_range(),
+ arg_list.args().join(", "),
+ );
+ }
+ }
+ } else if matches!(kind, UnwrapperKind::Option if ret_expr_str == "None") {
+ builder.replace(ret_expr_arg.syntax().text_range(), "()");
+ }
+ }
+ })
+}
+
+enum UnwrapperKind {
+ Option,
+ Result,
+}
+
+impl UnwrapperKind {
+ const ALL: &'static [UnwrapperKind] = &[UnwrapperKind::Option, UnwrapperKind::Result];
+
+ fn assist_id(&self) -> AssistId {
+ let s = match self {
+ UnwrapperKind::Option => "unwrap_option_return_type",
+ UnwrapperKind::Result => "unwrap_result_return_type",
+ };
+
+ AssistId(s, AssistKind::RefactorRewrite)
+ }
+
+ fn label(&self) -> &'static str {
+ match self {
+ UnwrapperKind::Option => "Unwrap Option return type",
+ UnwrapperKind::Result => "Unwrap Result return type",
+ }
+ }
+
+ fn core_type(&self, famous_defs: &FamousDefs<'_, '_>) -> Option<hir::Enum> {
+ match self {
+ UnwrapperKind::Option => famous_defs.core_option_Option(),
+ UnwrapperKind::Result => famous_defs.core_result_Result(),
+ }
+ }
+}
+
+fn tail_cb_impl(acc: &mut Vec<ast::Expr>, e: &ast::Expr) {
+ match e {
+ Expr::BreakExpr(break_expr) => {
+ if let Some(break_expr_arg) = break_expr.expr() {
+ for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(acc, e))
+ }
+ }
+ Expr::ReturnExpr(_) => {
+ // all return expressions have already been handled by the walk loop
+ }
+ e => acc.push(e.clone()),
+ }
+}
+
+// Tries to extract `T` from `Option<T>` or `Result<T, E>`.
+fn extract_wrapped_type(ty: &ast::Type) -> Option<ast::Type> {
+ let ast::Type::PathType(path_ty) = ty else {
+ return None;
+ };
+ let path = path_ty.path()?;
+ let segment = path.first_segment()?;
+ let generic_arg_list = segment.generic_arg_list()?;
+ let generic_args: Vec<_> = generic_arg_list.generic_args().collect();
+ let ast::GenericArg::TypeArg(happy_type) = generic_args.first()? else {
+ return None;
+ };
+ happy_type.ty()
+}
+
+fn is_unit_type(ty: &ast::Type) -> bool {
+ let ast::Type::TupleType(tuple) = ty else { return false };
+ tuple.fields().next().is_none()
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::tests::{check_assist_by_label, check_assist_not_applicable_by_label};
+
+ use super::*;
+
+ #[test]
+ fn unwrap_option_return_type_simple() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> Option<i3$02> {
+ let test = "test";
+ return Some(42i32);
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ let test = "test";
+ return 42i32;
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_unit_type() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> Option<()$0> {
+ Some(())
+}
+"#,
+ r#"
+fn foo() {
+}
+"#,
+ "Unwrap Option return type",
+ );
+
+ // Unformatted return type
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> Option<()$0>{
+ Some(())
+}
+"#,
+ r#"
+fn foo() {
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_none() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> Option<i3$02> {
+ if true {
+ Some(42)
+ } else {
+ None
+ }
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ if true {
+ 42
+ } else {
+ ()
+ }
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_ending_with_parent() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> Option<i3$02> {
+ if true {
+ Some(42)
+ } else {
+ foo()
+ }
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ if true {
+ 42
+ } else {
+ foo()
+ }
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_break_split_tail() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> Option<i3$02> {
+ loop {
+ break if true {
+ Some(1)
+ } else {
+ Some(0)
+ };
+ }
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ loop {
+ break if true {
+ 1
+ } else {
+ 0
+ };
+ }
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_closure() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() {
+ || -> Option<i32$0> {
+ let test = "test";
+ return Some(42i32);
+ };
+}
+"#,
+ r#"
+fn foo() {
+ || -> i32 {
+ let test = "test";
+ return 42i32;
+ };
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_return_type_bad_cursor() {
+ check_assist_not_applicable_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> i32 {
+ let test = "test";$0
+ return 42i32;
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_return_type_bad_cursor_closure() {
+ check_assist_not_applicable_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() {
+ || -> i32 {
+ let test = "test";$0
+ return 42i32;
+ };
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_closure_non_block() {
+ check_assist_not_applicable_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() { || -> i$032 3; }
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_return_type_already_not_option_std() {
+ check_assist_not_applicable_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> i32$0 {
+ let test = "test";
+ return 42i32;
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_return_type_already_not_option_closure() {
+ check_assist_not_applicable_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() {
+ || -> i32$0 {
+ let test = "test";
+ return 42i32;
+ };
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_with_tail() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() ->$0 Option<i32> {
+ let test = "test";
+ Some(42i32)
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ let test = "test";
+ 42i32
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_with_tail_closure() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() {
+ || ->$0 Option<i32> {
+ let test = "test";
+ Some(42i32)
+ };
+}
+"#,
+ r#"
+fn foo() {
+ || -> i32 {
+ let test = "test";
+ 42i32
+ };
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_with_tail_only() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> Option<i32$0> { Some(42i32) }
+"#,
+ r#"
+fn foo() -> i32 { 42i32 }
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_with_tail_block_like() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> Option<i32>$0 {
+ if true {
+ Some(42i32)
+ } else {
+ Some(24i32)
+ }
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ if true {
+ 42i32
+ } else {
+ 24i32
+ }
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_without_block_closure() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() {
+ || -> Option<i32>$0 {
+ if true {
+ Some(42i32)
+ } else {
+ Some(24i32)
+ }
+ };
+}
+"#,
+ r#"
+fn foo() {
+ || -> i32 {
+ if true {
+ 42i32
+ } else {
+ 24i32
+ }
+ };
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_with_nested_if() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> Option<i32>$0 {
+ if true {
+ if false {
+ Some(1)
+ } else {
+ Some(2)
+ }
+ } else {
+ Some(24i32)
+ }
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ if true {
+ if false {
+ 1
+ } else {
+ 2
+ }
+ } else {
+ 24i32
+ }
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_with_await() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+async fn foo() -> Option<i$032> {
+ if true {
+ if false {
+ Some(1.await)
+ } else {
+ Some(2.await)
+ }
+ } else {
+ Some(24i32.await)
+ }
+}
+"#,
+ r#"
+async fn foo() -> i32 {
+ if true {
+ if false {
+ 1.await
+ } else {
+ 2.await
+ }
+ } else {
+ 24i32.await
+ }
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_with_array() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> Option<[i32; 3]$0> { Some([1, 2, 3]) }
+"#,
+ r#"
+fn foo() -> [i32; 3] { [1, 2, 3] }
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_with_cast() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -$0> Option<i32> {
+ if true {
+ if false {
+ Some(1 as i32)
+ } else {
+ Some(2 as i32)
+ }
+ } else {
+ Some(24 as i32)
+ }
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ if true {
+ if false {
+ 1 as i32
+ } else {
+ 2 as i32
+ }
+ } else {
+ 24 as i32
+ }
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_with_tail_block_like_match() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> Option<i32$0> {
+ let my_var = 5;
+ match my_var {
+ 5 => Some(42i32),
+ _ => Some(24i32),
+ }
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ let my_var = 5;
+ match my_var {
+ 5 => 42i32,
+ _ => 24i32,
+ }
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_with_loop_with_tail() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> Option<i32$0> {
+ let my_var = 5;
+ loop {
+ println!("test");
+ 5
+ }
+ Some(my_var)
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ let my_var = 5;
+ loop {
+ println!("test");
+ 5
+ }
+ my_var
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_with_loop_in_let_stmt() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> Option<i32$0> {
+ let my_var = let x = loop {
+ break 1;
+ };
+ Some(my_var)
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ let my_var = let x = loop {
+ break 1;
+ };
+ my_var
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_with_tail_block_like_match_return_expr() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> Option<i32>$0 {
+ let my_var = 5;
+ let res = match my_var {
+ 5 => 42i32,
+ _ => return Some(24i32),
+ };
+ Some(res)
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ let my_var = 5;
+ let res = match my_var {
+ 5 => 42i32,
+ _ => return 24i32,
+ };
+ res
+}
+"#,
+ "Unwrap Option return type",
+ );
+
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> Option<i32$0> {
+ let my_var = 5;
+ let res = if my_var == 5 {
+ 42i32
+ } else {
+ return Some(24i32);
+ };
+ Some(res)
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ let my_var = 5;
+ let res = if my_var == 5 {
+ 42i32
+ } else {
+ return 24i32;
+ };
+ res
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_with_tail_block_like_match_deeper() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> Option<i32$0> {
+ let my_var = 5;
+ match my_var {
+ 5 => {
+ if true {
+ Some(42i32)
+ } else {
+ Some(25i32)
+ }
+ },
+ _ => {
+ let test = "test";
+ if test == "test" {
+ return Some(bar());
+ }
+ Some(53i32)
+ },
+ }
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ let my_var = 5;
+ match my_var {
+ 5 => {
+ if true {
+ 42i32
+ } else {
+ 25i32
+ }
+ },
+ _ => {
+ let test = "test";
+ if test == "test" {
+ return bar();
+ }
+ 53i32
+ },
+ }
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_with_tail_block_like_early_return() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> Option<i32$0> {
+ let test = "test";
+ if test == "test" {
+ return Some(24i32);
+ }
+ Some(53i32)
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ let test = "test";
+ if test == "test" {
+ return 24i32;
+ }
+ 53i32
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_in_tail_position() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo(num: i32) -> $0Option<i32> {
+ return Some(num)
+}
+"#,
+ r#"
+fn foo(num: i32) -> i32 {
+ return num
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_with_closure() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo(the_field: u32) -> Option<u32$0> {
+ let true_closure = || { return true; };
+ if the_field < 5 {
+ let mut i = 0;
+ if true_closure() {
+ return Some(99);
+ } else {
+ return Some(0);
+ }
+ }
+ Some(the_field)
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> u32 {
+ let true_closure = || { return true; };
+ if the_field < 5 {
+ let mut i = 0;
+ if true_closure() {
+ return 99;
+ } else {
+ return 0;
+ }
+ }
+ the_field
+}
+"#,
+ "Unwrap Option return type",
+ );
+
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo(the_field: u32) -> Option<u32$0> {
+ let true_closure = || {
+ return true;
+ };
+ if the_field < 5 {
+ let mut i = 0;
+
+
+ if true_closure() {
+ return Some(99);
+ } else {
+ return Some(0);
+ }
+ }
+ let t = None;
+
+ Some(t.unwrap_or_else(|| the_field))
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> u32 {
+ let true_closure = || {
+ return true;
+ };
+ if the_field < 5 {
+ let mut i = 0;
+
+
+ if true_closure() {
+ return 99;
+ } else {
+ return 0;
+ }
+ }
+ let t = None;
+
+ t.unwrap_or_else(|| the_field)
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_simple_with_weird_forms() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> Option<i32$0> {
+ let test = "test";
+ if test == "test" {
+ return Some(24i32);
+ }
+ let mut i = 0;
+ loop {
+ if i == 1 {
+ break Some(55);
+ }
+ i += 1;
+ }
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ let test = "test";
+ if test == "test" {
+ return 24i32;
+ }
+ let mut i = 0;
+ loop {
+ if i == 1 {
+ break 55;
+ }
+ i += 1;
+ }
+}
+"#,
+ "Unwrap Option return type",
+ );
+
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo(the_field: u32) -> Option<u32$0> {
+ if the_field < 5 {
+ let mut i = 0;
+ loop {
+ if i > 5 {
+ return Some(55u32);
+ }
+ i += 3;
+ }
+ match i {
+ 5 => return Some(99),
+ _ => return Some(0),
+ };
+ }
+ Some(the_field)
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> u32 {
+ if the_field < 5 {
+ let mut i = 0;
+ loop {
+ if i > 5 {
+ return 55u32;
+ }
+ i += 3;
+ }
+ match i {
+ 5 => return 99,
+ _ => return 0,
+ };
+ }
+ the_field
+}
+"#,
+ "Unwrap Option return type",
+ );
+
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo(the_field: u32) -> Option<u32$0> {
+ if the_field < 5 {
+ let mut i = 0;
+ match i {
+ 5 => return Some(99),
+ _ => return Some(0),
+ }
+ }
+ Some(the_field)
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> u32 {
+ if the_field < 5 {
+ let mut i = 0;
+ match i {
+ 5 => return 99,
+ _ => return 0,
+ }
+ }
+ the_field
+}
+"#,
+ "Unwrap Option return type",
+ );
+
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo(the_field: u32) -> Option<u32$0> {
+ if the_field < 5 {
+ let mut i = 0;
+ if i == 5 {
+ return Some(99)
+ } else {
+ return Some(0)
+ }
+ }
+ Some(the_field)
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> u32 {
+ if the_field < 5 {
+ let mut i = 0;
+ if i == 5 {
+ return 99
+ } else {
+ return 0
+ }
+ }
+ the_field
+}
+"#,
+ "Unwrap Option return type",
+ );
+
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option
+fn foo(the_field: u32) -> Option<u3$02> {
+ if the_field < 5 {
+ let mut i = 0;
+ if i == 5 {
+ return Some(99);
+ } else {
+ return Some(0);
+ }
+ }
+ Some(the_field)
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> u32 {
+ if the_field < 5 {
+ let mut i = 0;
+ if i == 5 {
+ return 99;
+ } else {
+ return 0;
+ }
+ }
+ the_field
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_option_return_type_nested_type() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option, result
+fn foo() -> Option<Result<i32$0, ()>> {
+ Some(Ok(42))
+}
+"#,
+ r#"
+fn foo() -> Result<i32, ()> {
+ Ok(42)
+}
+"#,
+ "Unwrap Option return type",
+ );
+
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option, result
+fn foo() -> Option<Result<Option<i32$0>, ()>> {
+ Some(Err())
+}
+"#,
+ r#"
+fn foo() -> Result<Option<i32>, ()> {
+ Err()
+}
+"#,
+ "Unwrap Option return type",
+ );
+
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: option, result, iterators
+fn foo() -> Option<impl Iterator<Item = i32>$0> {
+ Some(Some(42).into_iter())
+}
+"#,
+ r#"
+fn foo() -> impl Iterator<Item = i32> {
+ Some(42).into_iter()
+}
+"#,
+ "Unwrap Option return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> Result<i3$02> {
+ let test = "test";
+ return Ok(42i32);
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ let test = "test";
+ return 42i32;
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_unit_type() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> Result<(), Box<dyn Error$0>> {
+ Ok(())
+}
+"#,
+ r#"
+fn foo() {
+}
+"#,
+ "Unwrap Result return type",
+ );
+
+ // Unformatted return type
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> Result<(), Box<dyn Error$0>>{
+ Ok(())
+}
+"#,
+ r#"
+fn foo() {
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_ending_with_parent() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> Result<i32, Box<dyn Error$0>> {
+ if true {
+ Ok(42)
+ } else {
+ foo()
+ }
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ if true {
+ 42
+ } else {
+ foo()
+ }
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_break_split_tail() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> Result<i3$02, String> {
+ loop {
+ break if true {
+ Ok(1)
+ } else {
+ Ok(0)
+ };
+ }
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ loop {
+ break if true {
+ 1
+ } else {
+ 0
+ };
+ }
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_closure() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() {
+ || -> Result<i32$0> {
+ let test = "test";
+ return Ok(42i32);
+ };
+}
+"#,
+ r#"
+fn foo() {
+ || -> i32 {
+ let test = "test";
+ return 42i32;
+ };
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_return_type_bad_cursor() {
+ check_assist_not_applicable_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> i32 {
+ let test = "test";$0
+ return 42i32;
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_return_type_bad_cursor_closure() {
+ check_assist_not_applicable_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() {
+ || -> i32 {
+ let test = "test";$0
+ return 42i32;
+ };
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_closure_non_block() {
+ check_assist_not_applicable_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() { || -> i$032 3; }
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_return_type_already_not_result_std() {
+ check_assist_not_applicable_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> i32$0 {
+ let test = "test";
+ return 42i32;
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_return_type_already_not_result_closure() {
+ check_assist_not_applicable_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() {
+ || -> i32$0 {
+ let test = "test";
+ return 42i32;
+ };
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_with_tail() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() ->$0 Result<i32> {
+ let test = "test";
+ Ok(42i32)
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ let test = "test";
+ 42i32
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_with_tail_closure() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() {
+ || ->$0 Result<i32, String> {
+ let test = "test";
+ Ok(42i32)
+ };
+}
+"#,
+ r#"
+fn foo() {
+ || -> i32 {
+ let test = "test";
+ 42i32
+ };
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_with_tail_only() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> Result<i32$0> { Ok(42i32) }
+"#,
+ r#"
+fn foo() -> i32 { 42i32 }
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_with_tail_block_like() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> Result<i32>$0 {
+ if true {
+ Ok(42i32)
+ } else {
+ Ok(24i32)
+ }
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ if true {
+ 42i32
+ } else {
+ 24i32
+ }
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_without_block_closure() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() {
+ || -> Result<i32, String>$0 {
+ if true {
+ Ok(42i32)
+ } else {
+ Ok(24i32)
+ }
+ };
+}
+"#,
+ r#"
+fn foo() {
+ || -> i32 {
+ if true {
+ 42i32
+ } else {
+ 24i32
+ }
+ };
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_with_nested_if() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> Result<i32>$0 {
+ if true {
+ if false {
+ Ok(1)
+ } else {
+ Ok(2)
+ }
+ } else {
+ Ok(24i32)
+ }
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ if true {
+ if false {
+ 1
+ } else {
+ 2
+ }
+ } else {
+ 24i32
+ }
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_with_await() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+async fn foo() -> Result<i$032> {
+ if true {
+ if false {
+ Ok(1.await)
+ } else {
+ Ok(2.await)
+ }
+ } else {
+ Ok(24i32.await)
+ }
+}
+"#,
+ r#"
+async fn foo() -> i32 {
+ if true {
+ if false {
+ 1.await
+ } else {
+ 2.await
+ }
+ } else {
+ 24i32.await
+ }
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_with_array() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> Result<[i32; 3]$0> { Ok([1, 2, 3]) }
+"#,
+ r#"
+fn foo() -> [i32; 3] { [1, 2, 3] }
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_with_cast() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -$0> Result<i32> {
+ if true {
+ if false {
+ Ok(1 as i32)
+ } else {
+ Ok(2 as i32)
+ }
+ } else {
+ Ok(24 as i32)
+ }
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ if true {
+ if false {
+ 1 as i32
+ } else {
+ 2 as i32
+ }
+ } else {
+ 24 as i32
+ }
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_with_tail_block_like_match() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> Result<i32$0> {
+ let my_var = 5;
+ match my_var {
+ 5 => Ok(42i32),
+ _ => Ok(24i32),
+ }
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ let my_var = 5;
+ match my_var {
+ 5 => 42i32,
+ _ => 24i32,
+ }
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_with_loop_with_tail() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> Result<i32$0> {
+ let my_var = 5;
+ loop {
+ println!("test");
+ 5
+ }
+ Ok(my_var)
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ let my_var = 5;
+ loop {
+ println!("test");
+ 5
+ }
+ my_var
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_with_loop_in_let_stmt() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> Result<i32$0> {
+ let my_var = let x = loop {
+ break 1;
+ };
+ Ok(my_var)
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ let my_var = let x = loop {
+ break 1;
+ };
+ my_var
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_with_tail_block_like_match_return_expr() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> Result<i32>$0 {
+ let my_var = 5;
+ let res = match my_var {
+ 5 => 42i32,
+ _ => return Ok(24i32),
+ };
+ Ok(res)
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ let my_var = 5;
+ let res = match my_var {
+ 5 => 42i32,
+ _ => return 24i32,
+ };
+ res
+}
+"#,
+ "Unwrap Result return type",
+ );
+
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> Result<i32$0> {
+ let my_var = 5;
+ let res = if my_var == 5 {
+ 42i32
+ } else {
+ return Ok(24i32);
+ };
+ Ok(res)
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ let my_var = 5;
+ let res = if my_var == 5 {
+ 42i32
+ } else {
+ return 24i32;
+ };
+ res
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_with_tail_block_like_match_deeper() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> Result<i32$0> {
+ let my_var = 5;
+ match my_var {
+ 5 => {
+ if true {
+ Ok(42i32)
+ } else {
+ Ok(25i32)
+ }
+ },
+ _ => {
+ let test = "test";
+ if test == "test" {
+ return Ok(bar());
+ }
+ Ok(53i32)
+ },
+ }
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ let my_var = 5;
+ match my_var {
+ 5 => {
+ if true {
+ 42i32
+ } else {
+ 25i32
+ }
+ },
+ _ => {
+ let test = "test";
+ if test == "test" {
+ return bar();
+ }
+ 53i32
+ },
+ }
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_with_tail_block_like_early_return() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> Result<i32$0> {
+ let test = "test";
+ if test == "test" {
+ return Ok(24i32);
+ }
+ Ok(53i32)
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ let test = "test";
+ if test == "test" {
+ return 24i32;
+ }
+ 53i32
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_in_tail_position() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo(num: i32) -> $0Result<i32, String> {
+ return Ok(num)
+}
+"#,
+ r#"
+fn foo(num: i32) -> i32 {
+ return num
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_with_closure() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo(the_field: u32) -> Result<u32$0> {
+ let true_closure = || { return true; };
+ if the_field < 5 {
+ let mut i = 0;
+ if true_closure() {
+ return Ok(99);
+ } else {
+ return Ok(0);
+ }
+ }
+ Ok(the_field)
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> u32 {
+ let true_closure = || { return true; };
+ if the_field < 5 {
+ let mut i = 0;
+ if true_closure() {
+ return 99;
+ } else {
+ return 0;
+ }
+ }
+ the_field
+}
+"#,
+ "Unwrap Result return type",
+ );
+
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo(the_field: u32) -> Result<u32$0> {
+ let true_closure = || {
+ return true;
+ };
+ if the_field < 5 {
+ let mut i = 0;
+
+
+ if true_closure() {
+ return Ok(99);
+ } else {
+ return Ok(0);
+ }
+ }
+ let t = None;
+
+ Ok(t.unwrap_or_else(|| the_field))
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> u32 {
+ let true_closure = || {
+ return true;
+ };
+ if the_field < 5 {
+ let mut i = 0;
+
+
+ if true_closure() {
+ return 99;
+ } else {
+ return 0;
+ }
+ }
+ let t = None;
+
+ t.unwrap_or_else(|| the_field)
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_simple_with_weird_forms() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> Result<i32$0> {
+ let test = "test";
+ if test == "test" {
+ return Ok(24i32);
+ }
+ let mut i = 0;
+ loop {
+ if i == 1 {
+ break Ok(55);
+ }
+ i += 1;
+ }
+}
+"#,
+ r#"
+fn foo() -> i32 {
+ let test = "test";
+ if test == "test" {
+ return 24i32;
+ }
+ let mut i = 0;
+ loop {
+ if i == 1 {
+ break 55;
+ }
+ i += 1;
+ }
+}
+"#,
+ "Unwrap Result return type",
+ );
+
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo(the_field: u32) -> Result<u32$0> {
+ if the_field < 5 {
+ let mut i = 0;
+ loop {
+ if i > 5 {
+ return Ok(55u32);
+ }
+ i += 3;
+ }
+ match i {
+ 5 => return Ok(99),
+ _ => return Ok(0),
+ };
+ }
+ Ok(the_field)
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> u32 {
+ if the_field < 5 {
+ let mut i = 0;
+ loop {
+ if i > 5 {
+ return 55u32;
+ }
+ i += 3;
+ }
+ match i {
+ 5 => return 99,
+ _ => return 0,
+ };
+ }
+ the_field
+}
+"#,
+ "Unwrap Result return type",
+ );
+
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo(the_field: u32) -> Result<u32$0> {
+ if the_field < 5 {
+ let mut i = 0;
+ match i {
+ 5 => return Ok(99),
+ _ => return Ok(0),
+ }
+ }
+ Ok(the_field)
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> u32 {
+ if the_field < 5 {
+ let mut i = 0;
+ match i {
+ 5 => return 99,
+ _ => return 0,
+ }
+ }
+ the_field
+}
+"#,
+ "Unwrap Result return type",
+ );
+
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo(the_field: u32) -> Result<u32$0> {
+ if the_field < 5 {
+ let mut i = 0;
+ if i == 5 {
+ return Ok(99)
+ } else {
+ return Ok(0)
+ }
+ }
+ Ok(the_field)
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> u32 {
+ if the_field < 5 {
+ let mut i = 0;
+ if i == 5 {
+ return 99
+ } else {
+ return 0
+ }
+ }
+ the_field
+}
+"#,
+ "Unwrap Result return type",
+ );
+
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result
+fn foo(the_field: u32) -> Result<u3$02> {
+ if the_field < 5 {
+ let mut i = 0;
+ if i == 5 {
+ return Ok(99);
+ } else {
+ return Ok(0);
+ }
+ }
+ Ok(the_field)
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> u32 {
+ if the_field < 5 {
+ let mut i = 0;
+ if i == 5 {
+ return 99;
+ } else {
+ return 0;
+ }
+ }
+ the_field
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+
+ #[test]
+ fn unwrap_result_return_type_nested_type() {
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result, option
+fn foo() -> Result<Option<i32$0>, ()> {
+ Ok(Some(42))
+}
+"#,
+ r#"
+fn foo() -> Option<i32> {
+ Some(42)
+}
+"#,
+ "Unwrap Result return type",
+ );
+
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result, option
+fn foo() -> Result<Option<Result<i32$0, ()>>, ()> {
+ Ok(None)
+}
+"#,
+ r#"
+fn foo() -> Option<Result<i32, ()>> {
+ None
+}
+"#,
+ "Unwrap Result return type",
+ );
+
+ check_assist_by_label(
+ unwrap_return_type,
+ r#"
+//- minicore: result, option, iterators
+fn foo() -> Result<impl Iterator<Item = i32>$0, ()> {
+ Ok(Some(42).into_iter())
+}
+"#,
+ r#"
+fn foo() -> impl Iterator<Item = i32> {
+ Some(42).into_iter()
+}
+"#,
+ "Unwrap Result return type",
+ );
+ }
+}
diff --git a/crates/ide-assists/src/handlers/wrap_return_type.rs b/crates/ide-assists/src/handlers/wrap_return_type.rs
new file mode 100644
index 0000000000..2d918a5b1c
--- /dev/null
+++ b/crates/ide-assists/src/handlers/wrap_return_type.rs
@@ -0,0 +1,2457 @@
+use std::iter;
+
+use hir::HasSource;
+use ide_db::{
+ assists::GroupLabel,
+ famous_defs::FamousDefs,
+ syntax_helpers::node_ext::{for_each_tail_expr, walk_expr},
+};
+use itertools::Itertools;
+use syntax::{
+ ast::{self, make, Expr, HasGenericParams},
+ match_ast, ted, AstNode, ToSmolStr,
+};
+
+use crate::{AssistContext, AssistId, AssistKind, Assists};
+
+// Assist: wrap_return_type_in_option
+//
+// Wrap the function's return type into Option.
+//
+// ```
+// # //- minicore: option
+// fn foo() -> i32$0 { 42i32 }
+// ```
+// ->
+// ```
+// fn foo() -> Option<i32> { Some(42i32) }
+// ```
+
+// Assist: wrap_return_type_in_result
+//
+// Wrap the function's return type into Result.
+//
+// ```
+// # //- minicore: result
+// fn foo() -> i32$0 { 42i32 }
+// ```
+// ->
+// ```
+// fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }
+// ```
+
+pub(crate) fn wrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
+ let ret_type = ctx.find_node_at_offset::<ast::RetType>()?;
+ let parent = ret_type.syntax().parent()?;
+ let body = match_ast! {
+ match parent {
+ ast::Fn(func) => func.body()?,
+ ast::ClosureExpr(closure) => match closure.body()? {
+ Expr::BlockExpr(block) => block,
+ // closures require a block when a return type is specified
+ _ => return None,
+ },
+ _ => return None,
+ }
+ };
+
+ let type_ref = &ret_type.ty()?;
+ let ty = ctx.sema.resolve_type(type_ref)?.as_adt();
+ let famous_defs = FamousDefs(&ctx.sema, ctx.sema.scope(type_ref.syntax())?.krate());
+
+ for kind in WrapperKind::ALL {
+ let Some(core_wrapper) = kind.core_type(&famous_defs) else {
+ continue;
+ };
+
+ if matches!(ty, Some(hir::Adt::Enum(ret_type)) if ret_type == core_wrapper) {
+ // The return type is already wrapped
+ cov_mark::hit!(wrap_return_type_simple_return_type_already_wrapped);
+ continue;
+ }
+
+ acc.add_group(
+ &GroupLabel("Wrap return type in...".into()),
+ kind.assist_id(),
+ kind.label(),
+ type_ref.syntax().text_range(),
+ |edit| {
+ let alias = wrapper_alias(ctx, &core_wrapper, type_ref, kind.symbol());
+ let new_return_ty =
+ alias.unwrap_or_else(|| kind.wrap_type(type_ref)).clone_for_update();
+
+ let body = edit.make_mut(ast::Expr::BlockExpr(body.clone()));
+
+ let mut exprs_to_wrap = Vec::new();
+ let tail_cb = &mut |e: &_| tail_cb_impl(&mut exprs_to_wrap, e);
+ walk_expr(&body, &mut |expr| {
+ if let Expr::ReturnExpr(ret_expr) = expr {
+ if let Some(ret_expr_arg) = &ret_expr.expr() {
+ for_each_tail_expr(ret_expr_arg, tail_cb);
+ }
+ }
+ });
+ for_each_tail_expr(&body, tail_cb);
+
+ for ret_expr_arg in exprs_to_wrap {
+ let happy_wrapped = make::expr_call(
+ make::expr_path(make::ext::ident_path(kind.happy_ident())),
+ make::arg_list(iter::once(ret_expr_arg.clone())),
+ )
+ .clone_for_update();
+ ted::replace(ret_expr_arg.syntax(), happy_wrapped.syntax());
+ }
+
+ let old_return_ty = edit.make_mut(type_ref.clone());
+ ted::replace(old_return_ty.syntax(), new_return_ty.syntax());
+
+ if let WrapperKind::Result = kind {
+ // Add a placeholder snippet at the first generic argument that doesn't equal the return type.
+ // This is normally the error type, but that may not be the case when we inserted a type alias.
+ let args =
+ new_return_ty.syntax().descendants().find_map(ast::GenericArgList::cast);
+ let error_type_arg = args.and_then(|list| {
+ list.generic_args().find(|arg| match arg {
+ ast::GenericArg::TypeArg(_) => {
+ arg.syntax().text() != type_ref.syntax().text()
+ }
+ ast::GenericArg::LifetimeArg(_) => false,
+ _ => true,
+ })
+ });
+ if let Some(error_type_arg) = error_type_arg {
+ if let Some(cap) = ctx.config.snippet_cap {
+ edit.add_placeholder_snippet(cap, error_type_arg);
+ }
+ }
+ }
+ },
+ );
+ }
+
+ Some(())
+}
+
+enum WrapperKind {
+ Option,
+ Result,
+}
+
+impl WrapperKind {
+ const ALL: &'static [WrapperKind] = &[WrapperKind::Option, WrapperKind::Result];
+
+ fn assist_id(&self) -> AssistId {
+ let s = match self {
+ WrapperKind::Option => "wrap_return_type_in_option",
+ WrapperKind::Result => "wrap_return_type_in_result",
+ };
+
+ AssistId(s, AssistKind::RefactorRewrite)
+ }
+
+ fn label(&self) -> &'static str {
+ match self {
+ WrapperKind::Option => "Wrap return type in Option",
+ WrapperKind::Result => "Wrap return type in Result",
+ }
+ }
+
+ fn happy_ident(&self) -> &'static str {
+ match self {
+ WrapperKind::Option => "Some",
+ WrapperKind::Result => "Ok",
+ }
+ }
+
+ fn core_type(&self, famous_defs: &FamousDefs<'_, '_>) -> Option<hir::Enum> {
+ match self {
+ WrapperKind::Option => famous_defs.core_option_Option(),
+ WrapperKind::Result => famous_defs.core_result_Result(),
+ }
+ }
+
+ fn symbol(&self) -> hir::Symbol {
+ match self {
+ WrapperKind::Option => hir::sym::Option.clone(),
+ WrapperKind::Result => hir::sym::Result.clone(),
+ }
+ }
+
+ fn wrap_type(&self, type_ref: &ast::Type) -> ast::Type {
+ match self {
+ WrapperKind::Option => make::ext::ty_option(type_ref.clone()),
+ WrapperKind::Result => make::ext::ty_result(type_ref.clone(), make::ty_placeholder()),
+ }
+ }
+}
+
+// Try to find an wrapper type alias in the current scope (shadowing the default).
+fn wrapper_alias(
+ ctx: &AssistContext<'_>,
+ core_wrapper: &hir::Enum,
+ ret_type: &ast::Type,
+ wrapper: hir::Symbol,
+) -> Option<ast::Type> {
+ let wrapper_path = hir::ModPath::from_segments(
+ hir::PathKind::Plain,
+ iter::once(hir::Name::new_symbol_root(wrapper)),
+ );
+
+ ctx.sema.resolve_mod_path(ret_type.syntax(), &wrapper_path).and_then(|def| {
+ def.filter_map(|def| match def.as_module_def()? {
+ hir::ModuleDef::TypeAlias(alias) => {
+ let enum_ty = alias.ty(ctx.db()).as_adt()?.as_enum()?;
+ (&enum_ty == core_wrapper).then_some(alias)
+ }
+ _ => None,
+ })
+ .find_map(|alias| {
+ let mut inserted_ret_type = false;
+ let generic_params = alias
+ .source(ctx.db())?
+ .value
+ .generic_param_list()?
+ .generic_params()
+ .map(|param| match param {
+ // Replace the very first type parameter with the functions return type.
+ ast::GenericParam::TypeParam(_) if !inserted_ret_type => {
+ inserted_ret_type = true;
+ ret_type.to_smolstr()
+ }
+ ast::GenericParam::LifetimeParam(_) => make::lifetime("'_").to_smolstr(),
+ _ => make::ty_placeholder().to_smolstr(),
+ })
+ .join(", ");
+
+ let name = alias.name(ctx.db());
+ let name = name.as_str();
+ Some(make::ty(&format!("{name}<{generic_params}>")))
+ })
+ })
+}
+
+fn tail_cb_impl(acc: &mut Vec<ast::Expr>, e: &ast::Expr) {
+ match e {
+ Expr::BreakExpr(break_expr) => {
+ if let Some(break_expr_arg) = break_expr.expr() {
+ for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(acc, e))
+ }
+ }
+ Expr::ReturnExpr(_) => {
+ // all return expressions have already been handled by the walk loop
+ }
+ e => acc.push(e.clone()),
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::tests::{check_assist_by_label, check_assist_not_applicable_by_label};
+
+ use super::*;
+
+ #[test]
+ fn wrap_return_type_in_option_simple() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> i3$02 {
+ let test = "test";
+ return 42i32;
+}
+"#,
+ r#"
+fn foo() -> Option<i32> {
+ let test = "test";
+ return Some(42i32);
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_break_split_tail() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> i3$02 {
+ loop {
+ break if true {
+ 1
+ } else {
+ 0
+ };
+ }
+}
+"#,
+ r#"
+fn foo() -> Option<i32> {
+ loop {
+ break if true {
+ Some(1)
+ } else {
+ Some(0)
+ };
+ }
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_closure() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() {
+ || -> i32$0 {
+ let test = "test";
+ return 42i32;
+ };
+}
+"#,
+ r#"
+fn foo() {
+ || -> Option<i32> {
+ let test = "test";
+ return Some(42i32);
+ };
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_return_type_bad_cursor() {
+ check_assist_not_applicable_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> i32 {
+ let test = "test";$0
+ return 42i32;
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_return_type_bad_cursor_closure() {
+ check_assist_not_applicable_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() {
+ || -> i32 {
+ let test = "test";$0
+ return 42i32;
+ };
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_closure_non_block() {
+ check_assist_not_applicable_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() { || -> i$032 3; }
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_return_type_already_option_std() {
+ check_assist_not_applicable_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> core::option::Option<i32$0> {
+ let test = "test";
+ return 42i32;
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_return_type_already_option() {
+ cov_mark::check!(wrap_return_type_simple_return_type_already_wrapped);
+ check_assist_not_applicable_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> Option<i32$0> {
+ let test = "test";
+ return 42i32;
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_return_type_already_option_closure() {
+ check_assist_not_applicable_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() {
+ || -> Option<i32$0, String> {
+ let test = "test";
+ return 42i32;
+ };
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_with_cursor() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> $0i32 {
+ let test = "test";
+ return 42i32;
+}
+"#,
+ r#"
+fn foo() -> Option<i32> {
+ let test = "test";
+ return Some(42i32);
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_with_tail() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() ->$0 i32 {
+ let test = "test";
+ 42i32
+}
+"#,
+ r#"
+fn foo() -> Option<i32> {
+ let test = "test";
+ Some(42i32)
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_with_tail_closure() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() {
+ || ->$0 i32 {
+ let test = "test";
+ 42i32
+ };
+}
+"#,
+ r#"
+fn foo() {
+ || -> Option<i32> {
+ let test = "test";
+ Some(42i32)
+ };
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_with_tail_only() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> i32$0 { 42i32 }
+"#,
+ r#"
+fn foo() -> Option<i32> { Some(42i32) }
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_with_tail_block_like() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> i32$0 {
+ if true {
+ 42i32
+ } else {
+ 24i32
+ }
+}
+"#,
+ r#"
+fn foo() -> Option<i32> {
+ if true {
+ Some(42i32)
+ } else {
+ Some(24i32)
+ }
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_without_block_closure() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() {
+ || -> i32$0 {
+ if true {
+ 42i32
+ } else {
+ 24i32
+ }
+ };
+}
+"#,
+ r#"
+fn foo() {
+ || -> Option<i32> {
+ if true {
+ Some(42i32)
+ } else {
+ Some(24i32)
+ }
+ };
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_with_nested_if() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> i32$0 {
+ if true {
+ if false {
+ 1
+ } else {
+ 2
+ }
+ } else {
+ 24i32
+ }
+}
+"#,
+ r#"
+fn foo() -> Option<i32> {
+ if true {
+ if false {
+ Some(1)
+ } else {
+ Some(2)
+ }
+ } else {
+ Some(24i32)
+ }
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_with_await() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+async fn foo() -> i$032 {
+ if true {
+ if false {
+ 1.await
+ } else {
+ 2.await
+ }
+ } else {
+ 24i32.await
+ }
+}
+"#,
+ r#"
+async fn foo() -> Option<i32> {
+ if true {
+ if false {
+ Some(1.await)
+ } else {
+ Some(2.await)
+ }
+ } else {
+ Some(24i32.await)
+ }
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_with_array() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> [i32;$0 3] { [1, 2, 3] }
+"#,
+ r#"
+fn foo() -> Option<[i32; 3]> { Some([1, 2, 3]) }
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_with_cast() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -$0> i32 {
+ if true {
+ if false {
+ 1 as i32
+ } else {
+ 2 as i32
+ }
+ } else {
+ 24 as i32
+ }
+}
+"#,
+ r#"
+fn foo() -> Option<i32> {
+ if true {
+ if false {
+ Some(1 as i32)
+ } else {
+ Some(2 as i32)
+ }
+ } else {
+ Some(24 as i32)
+ }
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_with_tail_block_like_match() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> i32$0 {
+ let my_var = 5;
+ match my_var {
+ 5 => 42i32,
+ _ => 24i32,
+ }
+}
+"#,
+ r#"
+fn foo() -> Option<i32> {
+ let my_var = 5;
+ match my_var {
+ 5 => Some(42i32),
+ _ => Some(24i32),
+ }
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_with_loop_with_tail() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> i32$0 {
+ let my_var = 5;
+ loop {
+ println!("test");
+ 5
+ }
+ my_var
+}
+"#,
+ r#"
+fn foo() -> Option<i32> {
+ let my_var = 5;
+ loop {
+ println!("test");
+ 5
+ }
+ Some(my_var)
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_with_loop_in_let_stmt() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> i32$0 {
+ let my_var = let x = loop {
+ break 1;
+ };
+ my_var
+}
+"#,
+ r#"
+fn foo() -> Option<i32> {
+ let my_var = let x = loop {
+ break 1;
+ };
+ Some(my_var)
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_with_tail_block_like_match_return_expr() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> i32$0 {
+ let my_var = 5;
+ let res = match my_var {
+ 5 => 42i32,
+ _ => return 24i32,
+ };
+ res
+}
+"#,
+ r#"
+fn foo() -> Option<i32> {
+ let my_var = 5;
+ let res = match my_var {
+ 5 => 42i32,
+ _ => return Some(24i32),
+ };
+ Some(res)
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> i32$0 {
+ let my_var = 5;
+ let res = if my_var == 5 {
+ 42i32
+ } else {
+ return 24i32;
+ };
+ res
+}
+"#,
+ r#"
+fn foo() -> Option<i32> {
+ let my_var = 5;
+ let res = if my_var == 5 {
+ 42i32
+ } else {
+ return Some(24i32);
+ };
+ Some(res)
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_with_tail_block_like_match_deeper() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> i32$0 {
+ let my_var = 5;
+ match my_var {
+ 5 => {
+ if true {
+ 42i32
+ } else {
+ 25i32
+ }
+ },
+ _ => {
+ let test = "test";
+ if test == "test" {
+ return bar();
+ }
+ 53i32
+ },
+ }
+}
+"#,
+ r#"
+fn foo() -> Option<i32> {
+ let my_var = 5;
+ match my_var {
+ 5 => {
+ if true {
+ Some(42i32)
+ } else {
+ Some(25i32)
+ }
+ },
+ _ => {
+ let test = "test";
+ if test == "test" {
+ return Some(bar());
+ }
+ Some(53i32)
+ },
+ }
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_with_tail_block_like_early_return() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> i$032 {
+ let test = "test";
+ if test == "test" {
+ return 24i32;
+ }
+ 53i32
+}
+"#,
+ r#"
+fn foo() -> Option<i32> {
+ let test = "test";
+ if test == "test" {
+ return Some(24i32);
+ }
+ Some(53i32)
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_in_option_tail_position() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo(num: i32) -> $0i32 {
+ return num
+}
+"#,
+ r#"
+fn foo(num: i32) -> Option<i32> {
+ return Some(num)
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_with_closure() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo(the_field: u32) ->$0 u32 {
+ let true_closure = || { return true; };
+ if the_field < 5 {
+ let mut i = 0;
+ if true_closure() {
+ return 99;
+ } else {
+ return 0;
+ }
+ }
+ the_field
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> Option<u32> {
+ let true_closure = || { return true; };
+ if the_field < 5 {
+ let mut i = 0;
+ if true_closure() {
+ return Some(99);
+ } else {
+ return Some(0);
+ }
+ }
+ Some(the_field)
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo(the_field: u32) -> u32$0 {
+ let true_closure = || {
+ return true;
+ };
+ if the_field < 5 {
+ let mut i = 0;
+
+
+ if true_closure() {
+ return 99;
+ } else {
+ return 0;
+ }
+ }
+ let t = None;
+
+ t.unwrap_or_else(|| the_field)
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> Option<u32> {
+ let true_closure = || {
+ return true;
+ };
+ if the_field < 5 {
+ let mut i = 0;
+
+
+ if true_closure() {
+ return Some(99);
+ } else {
+ return Some(0);
+ }
+ }
+ let t = None;
+
+ Some(t.unwrap_or_else(|| the_field))
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_option_simple_with_weird_forms() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> i32$0 {
+ let test = "test";
+ if test == "test" {
+ return 24i32;
+ }
+ let mut i = 0;
+ loop {
+ if i == 1 {
+ break 55;
+ }
+ i += 1;
+ }
+}
+"#,
+ r#"
+fn foo() -> Option<i32> {
+ let test = "test";
+ if test == "test" {
+ return Some(24i32);
+ }
+ let mut i = 0;
+ loop {
+ if i == 1 {
+ break Some(55);
+ }
+ i += 1;
+ }
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo(the_field: u32) -> u32$0 {
+ if the_field < 5 {
+ let mut i = 0;
+ loop {
+ if i > 5 {
+ return 55u32;
+ }
+ i += 3;
+ }
+ match i {
+ 5 => return 99,
+ _ => return 0,
+ };
+ }
+ the_field
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> Option<u32> {
+ if the_field < 5 {
+ let mut i = 0;
+ loop {
+ if i > 5 {
+ return Some(55u32);
+ }
+ i += 3;
+ }
+ match i {
+ 5 => return Some(99),
+ _ => return Some(0),
+ };
+ }
+ Some(the_field)
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo(the_field: u32) -> u3$02 {
+ if the_field < 5 {
+ let mut i = 0;
+ match i {
+ 5 => return 99,
+ _ => return 0,
+ }
+ }
+ the_field
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> Option<u32> {
+ if the_field < 5 {
+ let mut i = 0;
+ match i {
+ 5 => return Some(99),
+ _ => return Some(0),
+ }
+ }
+ Some(the_field)
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo(the_field: u32) -> u32$0 {
+ if the_field < 5 {
+ let mut i = 0;
+ if i == 5 {
+ return 99
+ } else {
+ return 0
+ }
+ }
+ the_field
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> Option<u32> {
+ if the_field < 5 {
+ let mut i = 0;
+ if i == 5 {
+ return Some(99)
+ } else {
+ return Some(0)
+ }
+ }
+ Some(the_field)
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo(the_field: u32) -> $0u32 {
+ if the_field < 5 {
+ let mut i = 0;
+ if i == 5 {
+ return 99;
+ } else {
+ return 0;
+ }
+ }
+ the_field
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> Option<u32> {
+ if the_field < 5 {
+ let mut i = 0;
+ if i == 5 {
+ return Some(99);
+ } else {
+ return Some(0);
+ }
+ }
+ Some(the_field)
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_local_option_type() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+type Option<T> = core::option::Option<T>;
+
+fn foo() -> i3$02 {
+ return 42i32;
+}
+"#,
+ r#"
+type Option<T> = core::option::Option<T>;
+
+fn foo() -> Option<i32> {
+ return Some(42i32);
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+type Option2<T> = core::option::Option<T>;
+
+fn foo() -> i3$02 {
+ return 42i32;
+}
+"#,
+ r#"
+type Option2<T> = core::option::Option<T>;
+
+fn foo() -> Option<i32> {
+ return Some(42i32);
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_imported_local_option_type() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+mod some_module {
+ pub type Option<T> = core::option::Option<T>;
+}
+
+use some_module::Option;
+
+fn foo() -> i3$02 {
+ return 42i32;
+}
+"#,
+ r#"
+mod some_module {
+ pub type Option<T> = core::option::Option<T>;
+}
+
+use some_module::Option;
+
+fn foo() -> Option<i32> {
+ return Some(42i32);
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+mod some_module {
+ pub type Option<T> = core::option::Option<T>;
+}
+
+use some_module::*;
+
+fn foo() -> i3$02 {
+ return 42i32;
+}
+"#,
+ r#"
+mod some_module {
+ pub type Option<T> = core::option::Option<T>;
+}
+
+use some_module::*;
+
+fn foo() -> Option<i32> {
+ return Some(42i32);
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_local_option_type_from_function_body() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> i3$02 {
+ type Option<T> = core::option::Option<T>;
+ 0
+}
+"#,
+ r#"
+fn foo() -> Option<i32> {
+ type Option<T> = core::option::Option<T>;
+ Some(0)
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_local_option_type_already_using_alias() {
+ check_assist_not_applicable_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+pub type Option<T> = core::option::Option<T>;
+
+fn foo() -> Option<i3$02> {
+ return Some(42i32);
+}
+"#,
+ WrapperKind::Option.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> i3$02 {
+ let test = "test";
+ return 42i32;
+}
+"#,
+ r#"
+fn foo() -> Result<i32, ${0:_}> {
+ let test = "test";
+ return Ok(42i32);
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_break_split_tail() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> i3$02 {
+ loop {
+ break if true {
+ 1
+ } else {
+ 0
+ };
+ }
+}
+"#,
+ r#"
+fn foo() -> Result<i32, ${0:_}> {
+ loop {
+ break if true {
+ Ok(1)
+ } else {
+ Ok(0)
+ };
+ }
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_closure() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() {
+ || -> i32$0 {
+ let test = "test";
+ return 42i32;
+ };
+}
+"#,
+ r#"
+fn foo() {
+ || -> Result<i32, ${0:_}> {
+ let test = "test";
+ return Ok(42i32);
+ };
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_return_type_bad_cursor() {
+ check_assist_not_applicable_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> i32 {
+ let test = "test";$0
+ return 42i32;
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_return_type_bad_cursor_closure() {
+ check_assist_not_applicable_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() {
+ || -> i32 {
+ let test = "test";$0
+ return 42i32;
+ };
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_closure_non_block() {
+ check_assist_not_applicable_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() { || -> i$032 3; }
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_return_type_already_result_std() {
+ check_assist_not_applicable_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> core::result::Result<i32$0, String> {
+ let test = "test";
+ return 42i32;
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_return_type_already_result() {
+ cov_mark::check!(wrap_return_type_simple_return_type_already_wrapped);
+ check_assist_not_applicable_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> Result<i32$0, String> {
+ let test = "test";
+ return 42i32;
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_return_type_already_result_closure() {
+ check_assist_not_applicable_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() {
+ || -> Result<i32$0, String> {
+ let test = "test";
+ return 42i32;
+ };
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_with_cursor() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> $0i32 {
+ let test = "test";
+ return 42i32;
+}
+"#,
+ r#"
+fn foo() -> Result<i32, ${0:_}> {
+ let test = "test";
+ return Ok(42i32);
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_with_tail() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() ->$0 i32 {
+ let test = "test";
+ 42i32
+}
+"#,
+ r#"
+fn foo() -> Result<i32, ${0:_}> {
+ let test = "test";
+ Ok(42i32)
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_with_tail_closure() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() {
+ || ->$0 i32 {
+ let test = "test";
+ 42i32
+ };
+}
+"#,
+ r#"
+fn foo() {
+ || -> Result<i32, ${0:_}> {
+ let test = "test";
+ Ok(42i32)
+ };
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_with_tail_only() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> i32$0 { 42i32 }
+"#,
+ r#"
+fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_with_tail_block_like() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> i32$0 {
+ if true {
+ 42i32
+ } else {
+ 24i32
+ }
+}
+"#,
+ r#"
+fn foo() -> Result<i32, ${0:_}> {
+ if true {
+ Ok(42i32)
+ } else {
+ Ok(24i32)
+ }
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_without_block_closure() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() {
+ || -> i32$0 {
+ if true {
+ 42i32
+ } else {
+ 24i32
+ }
+ };
+}
+"#,
+ r#"
+fn foo() {
+ || -> Result<i32, ${0:_}> {
+ if true {
+ Ok(42i32)
+ } else {
+ Ok(24i32)
+ }
+ };
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_with_nested_if() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> i32$0 {
+ if true {
+ if false {
+ 1
+ } else {
+ 2
+ }
+ } else {
+ 24i32
+ }
+}
+"#,
+ r#"
+fn foo() -> Result<i32, ${0:_}> {
+ if true {
+ if false {
+ Ok(1)
+ } else {
+ Ok(2)
+ }
+ } else {
+ Ok(24i32)
+ }
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_with_await() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+async fn foo() -> i$032 {
+ if true {
+ if false {
+ 1.await
+ } else {
+ 2.await
+ }
+ } else {
+ 24i32.await
+ }
+}
+"#,
+ r#"
+async fn foo() -> Result<i32, ${0:_}> {
+ if true {
+ if false {
+ Ok(1.await)
+ } else {
+ Ok(2.await)
+ }
+ } else {
+ Ok(24i32.await)
+ }
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_with_array() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> [i32;$0 3] { [1, 2, 3] }
+"#,
+ r#"
+fn foo() -> Result<[i32; 3], ${0:_}> { Ok([1, 2, 3]) }
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_with_cast() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -$0> i32 {
+ if true {
+ if false {
+ 1 as i32
+ } else {
+ 2 as i32
+ }
+ } else {
+ 24 as i32
+ }
+}
+"#,
+ r#"
+fn foo() -> Result<i32, ${0:_}> {
+ if true {
+ if false {
+ Ok(1 as i32)
+ } else {
+ Ok(2 as i32)
+ }
+ } else {
+ Ok(24 as i32)
+ }
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_with_tail_block_like_match() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> i32$0 {
+ let my_var = 5;
+ match my_var {
+ 5 => 42i32,
+ _ => 24i32,
+ }
+}
+"#,
+ r#"
+fn foo() -> Result<i32, ${0:_}> {
+ let my_var = 5;
+ match my_var {
+ 5 => Ok(42i32),
+ _ => Ok(24i32),
+ }
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_with_loop_with_tail() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> i32$0 {
+ let my_var = 5;
+ loop {
+ println!("test");
+ 5
+ }
+ my_var
+}
+"#,
+ r#"
+fn foo() -> Result<i32, ${0:_}> {
+ let my_var = 5;
+ loop {
+ println!("test");
+ 5
+ }
+ Ok(my_var)
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_with_loop_in_let_stmt() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> i32$0 {
+ let my_var = let x = loop {
+ break 1;
+ };
+ my_var
+}
+"#,
+ r#"
+fn foo() -> Result<i32, ${0:_}> {
+ let my_var = let x = loop {
+ break 1;
+ };
+ Ok(my_var)
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_with_tail_block_like_match_return_expr() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> i32$0 {
+ let my_var = 5;
+ let res = match my_var {
+ 5 => 42i32,
+ _ => return 24i32,
+ };
+ res
+}
+"#,
+ r#"
+fn foo() -> Result<i32, ${0:_}> {
+ let my_var = 5;
+ let res = match my_var {
+ 5 => 42i32,
+ _ => return Ok(24i32),
+ };
+ Ok(res)
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> i32$0 {
+ let my_var = 5;
+ let res = if my_var == 5 {
+ 42i32
+ } else {
+ return 24i32;
+ };
+ res
+}
+"#,
+ r#"
+fn foo() -> Result<i32, ${0:_}> {
+ let my_var = 5;
+ let res = if my_var == 5 {
+ 42i32
+ } else {
+ return Ok(24i32);
+ };
+ Ok(res)
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_with_tail_block_like_match_deeper() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> i32$0 {
+ let my_var = 5;
+ match my_var {
+ 5 => {
+ if true {
+ 42i32
+ } else {
+ 25i32
+ }
+ },
+ _ => {
+ let test = "test";
+ if test == "test" {
+ return bar();
+ }
+ 53i32
+ },
+ }
+}
+"#,
+ r#"
+fn foo() -> Result<i32, ${0:_}> {
+ let my_var = 5;
+ match my_var {
+ 5 => {
+ if true {
+ Ok(42i32)
+ } else {
+ Ok(25i32)
+ }
+ },
+ _ => {
+ let test = "test";
+ if test == "test" {
+ return Ok(bar());
+ }
+ Ok(53i32)
+ },
+ }
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_with_tail_block_like_early_return() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> i$032 {
+ let test = "test";
+ if test == "test" {
+ return 24i32;
+ }
+ 53i32
+}
+"#,
+ r#"
+fn foo() -> Result<i32, ${0:_}> {
+ let test = "test";
+ if test == "test" {
+ return Ok(24i32);
+ }
+ Ok(53i32)
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_in_result_tail_position() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo(num: i32) -> $0i32 {
+ return num
+}
+"#,
+ r#"
+fn foo(num: i32) -> Result<i32, ${0:_}> {
+ return Ok(num)
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_with_closure() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo(the_field: u32) ->$0 u32 {
+ let true_closure = || { return true; };
+ if the_field < 5 {
+ let mut i = 0;
+ if true_closure() {
+ return 99;
+ } else {
+ return 0;
+ }
+ }
+ the_field
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> Result<u32, ${0:_}> {
+ let true_closure = || { return true; };
+ if the_field < 5 {
+ let mut i = 0;
+ if true_closure() {
+ return Ok(99);
+ } else {
+ return Ok(0);
+ }
+ }
+ Ok(the_field)
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo(the_field: u32) -> u32$0 {
+ let true_closure = || {
+ return true;
+ };
+ if the_field < 5 {
+ let mut i = 0;
+
+
+ if true_closure() {
+ return 99;
+ } else {
+ return 0;
+ }
+ }
+ let t = None;
+
+ t.unwrap_or_else(|| the_field)
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> Result<u32, ${0:_}> {
+ let true_closure = || {
+ return true;
+ };
+ if the_field < 5 {
+ let mut i = 0;
+
+
+ if true_closure() {
+ return Ok(99);
+ } else {
+ return Ok(0);
+ }
+ }
+ let t = None;
+
+ Ok(t.unwrap_or_else(|| the_field))
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_result_simple_with_weird_forms() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> i32$0 {
+ let test = "test";
+ if test == "test" {
+ return 24i32;
+ }
+ let mut i = 0;
+ loop {
+ if i == 1 {
+ break 55;
+ }
+ i += 1;
+ }
+}
+"#,
+ r#"
+fn foo() -> Result<i32, ${0:_}> {
+ let test = "test";
+ if test == "test" {
+ return Ok(24i32);
+ }
+ let mut i = 0;
+ loop {
+ if i == 1 {
+ break Ok(55);
+ }
+ i += 1;
+ }
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo(the_field: u32) -> u32$0 {
+ if the_field < 5 {
+ let mut i = 0;
+ loop {
+ if i > 5 {
+ return 55u32;
+ }
+ i += 3;
+ }
+ match i {
+ 5 => return 99,
+ _ => return 0,
+ };
+ }
+ the_field
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> Result<u32, ${0:_}> {
+ if the_field < 5 {
+ let mut i = 0;
+ loop {
+ if i > 5 {
+ return Ok(55u32);
+ }
+ i += 3;
+ }
+ match i {
+ 5 => return Ok(99),
+ _ => return Ok(0),
+ };
+ }
+ Ok(the_field)
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo(the_field: u32) -> u3$02 {
+ if the_field < 5 {
+ let mut i = 0;
+ match i {
+ 5 => return 99,
+ _ => return 0,
+ }
+ }
+ the_field
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> Result<u32, ${0:_}> {
+ if the_field < 5 {
+ let mut i = 0;
+ match i {
+ 5 => return Ok(99),
+ _ => return Ok(0),
+ }
+ }
+ Ok(the_field)
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo(the_field: u32) -> u32$0 {
+ if the_field < 5 {
+ let mut i = 0;
+ if i == 5 {
+ return 99
+ } else {
+ return 0
+ }
+ }
+ the_field
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> Result<u32, ${0:_}> {
+ if the_field < 5 {
+ let mut i = 0;
+ if i == 5 {
+ return Ok(99)
+ } else {
+ return Ok(0)
+ }
+ }
+ Ok(the_field)
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo(the_field: u32) -> $0u32 {
+ if the_field < 5 {
+ let mut i = 0;
+ if i == 5 {
+ return 99;
+ } else {
+ return 0;
+ }
+ }
+ the_field
+}
+"#,
+ r#"
+fn foo(the_field: u32) -> Result<u32, ${0:_}> {
+ if the_field < 5 {
+ let mut i = 0;
+ if i == 5 {
+ return Ok(99);
+ } else {
+ return Ok(0);
+ }
+ }
+ Ok(the_field)
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_local_result_type() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+type Result<T> = core::result::Result<T, ()>;
+
+fn foo() -> i3$02 {
+ return 42i32;
+}
+"#,
+ r#"
+type Result<T> = core::result::Result<T, ()>;
+
+fn foo() -> Result<i32> {
+ return Ok(42i32);
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+type Result2<T> = core::result::Result<T, ()>;
+
+fn foo() -> i3$02 {
+ return 42i32;
+}
+"#,
+ r#"
+type Result2<T> = core::result::Result<T, ()>;
+
+fn foo() -> Result<i32, ${0:_}> {
+ return Ok(42i32);
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_imported_local_result_type() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+mod some_module {
+ pub type Result<T> = core::result::Result<T, ()>;
+}
+
+use some_module::Result;
+
+fn foo() -> i3$02 {
+ return 42i32;
+}
+"#,
+ r#"
+mod some_module {
+ pub type Result<T> = core::result::Result<T, ()>;
+}
+
+use some_module::Result;
+
+fn foo() -> Result<i32> {
+ return Ok(42i32);
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+mod some_module {
+ pub type Result<T> = core::result::Result<T, ()>;
+}
+
+use some_module::*;
+
+fn foo() -> i3$02 {
+ return 42i32;
+}
+"#,
+ r#"
+mod some_module {
+ pub type Result<T> = core::result::Result<T, ()>;
+}
+
+use some_module::*;
+
+fn foo() -> Result<i32> {
+ return Ok(42i32);
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_local_result_type_from_function_body() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> i3$02 {
+ type Result<T> = core::result::Result<T, ()>;
+ 0
+}
+"#,
+ r#"
+fn foo() -> Result<i32, ${0:_}> {
+ type Result<T> = core::result::Result<T, ()>;
+ Ok(0)
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_local_result_type_already_using_alias() {
+ check_assist_not_applicable_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+pub type Result<T> = core::result::Result<T, ()>;
+
+fn foo() -> Result<i3$02> {
+ return Ok(42i32);
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn wrap_return_type_in_local_result_type_multiple_generics() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+type Result<T, E> = core::result::Result<T, E>;
+
+fn foo() -> i3$02 {
+ 0
+}
+"#,
+ r#"
+type Result<T, E> = core::result::Result<T, E>;
+
+fn foo() -> Result<i32, ${0:_}> {
+ Ok(0)
+}
+"#,
+ WrapperKind::Result.label(),
+ );
+
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+type Result<T, E> = core::result::Result<Foo<T, E>, ()>;
+
+fn foo() -> i3$02 {
+ 0
+}
+ "#,
+ r#"
+type Result<T, E> = core::result::Result<Foo<T, E>, ()>;
+
+fn foo() -> Result<i32, ${0:_}> {
+ Ok(0)
+}
+ "#,
+ WrapperKind::Result.label(),
+ );
+
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+type Result<'a, T, E> = core::result::Result<Foo<T, E>, &'a ()>;
+
+fn foo() -> i3$02 {
+ 0
+}
+ "#,
+ r#"
+type Result<'a, T, E> = core::result::Result<Foo<T, E>, &'a ()>;
+
+fn foo() -> Result<'_, i32, ${0:_}> {
+ Ok(0)
+}
+ "#,
+ WrapperKind::Result.label(),
+ );
+
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+type Result<T, const N: usize> = core::result::Result<Foo<T>, Bar<N>>;
+
+fn foo() -> i3$02 {
+ 0
+}
+ "#,
+ r#"
+type Result<T, const N: usize> = core::result::Result<Foo<T>, Bar<N>>;
+
+fn foo() -> Result<i32, ${0:_}> {
+ Ok(0)
+}
+ "#,
+ WrapperKind::Result.label(),
+ );
+ }
+}
diff --git a/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs b/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs
deleted file mode 100644
index 8f0e9b4fe0..0000000000
--- a/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs
+++ /dev/null
@@ -1,1268 +0,0 @@
-use std::iter;
-
-use hir::HasSource;
-use ide_db::{
- famous_defs::FamousDefs,
- syntax_helpers::node_ext::{for_each_tail_expr, walk_expr},
-};
-use itertools::Itertools;
-use syntax::{
- ast::{self, make, Expr, HasGenericParams},
- match_ast, ted, AstNode, ToSmolStr,
-};
-
-use crate::{AssistContext, AssistId, AssistKind, Assists};
-
-// Assist: wrap_return_type_in_result
-//
-// Wrap the function's return type into Result.
-//
-// ```
-// # //- minicore: result
-// fn foo() -> i32$0 { 42i32 }
-// ```
-// ->
-// ```
-// fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }
-// ```
-pub(crate) fn wrap_return_type_in_result(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
- let ret_type = ctx.find_node_at_offset::<ast::RetType>()?;
- let parent = ret_type.syntax().parent()?;
- let body = match_ast! {
- match parent {
- ast::Fn(func) => func.body()?,
- ast::ClosureExpr(closure) => match closure.body()? {
- Expr::BlockExpr(block) => block,
- // closures require a block when a return type is specified
- _ => return None,
- },
- _ => return None,
- }
- };
-
- let type_ref = &ret_type.ty()?;
- let core_result =
- FamousDefs(&ctx.sema, ctx.sema.scope(type_ref.syntax())?.krate()).core_result_Result()?;
-
- let ty = ctx.sema.resolve_type(type_ref)?.as_adt();
- if matches!(ty, Some(hir::Adt::Enum(ret_type)) if ret_type == core_result) {
- // The return type is already wrapped in a Result
- cov_mark::hit!(wrap_return_type_in_result_simple_return_type_already_result);
- return None;
- }
-
- acc.add(
- AssistId("wrap_return_type_in_result", AssistKind::RefactorRewrite),
- "Wrap return type in Result",
- type_ref.syntax().text_range(),
- |edit| {
- let new_result_ty = result_type(ctx, &core_result, type_ref).clone_for_update();
- let body = edit.make_mut(ast::Expr::BlockExpr(body));
-
- let mut exprs_to_wrap = Vec::new();
- let tail_cb = &mut |e: &_| tail_cb_impl(&mut exprs_to_wrap, e);
- walk_expr(&body, &mut |expr| {
- if let Expr::ReturnExpr(ret_expr) = expr {
- if let Some(ret_expr_arg) = &ret_expr.expr() {
- for_each_tail_expr(ret_expr_arg, tail_cb);
- }
- }
- });
- for_each_tail_expr(&body, tail_cb);
-
- for ret_expr_arg in exprs_to_wrap {
- let ok_wrapped = make::expr_call(
- make::expr_path(make::ext::ident_path("Ok")),
- make::arg_list(iter::once(ret_expr_arg.clone())),
- )
- .clone_for_update();
- ted::replace(ret_expr_arg.syntax(), ok_wrapped.syntax());
- }
-
- let old_result_ty = edit.make_mut(type_ref.clone());
- ted::replace(old_result_ty.syntax(), new_result_ty.syntax());
-
- // Add a placeholder snippet at the first generic argument that doesn't equal the return type.
- // This is normally the error type, but that may not be the case when we inserted a type alias.
- let args = new_result_ty.syntax().descendants().find_map(ast::GenericArgList::cast);
- let error_type_arg = args.and_then(|list| {
- list.generic_args().find(|arg| match arg {
- ast::GenericArg::TypeArg(_) => arg.syntax().text() != type_ref.syntax().text(),
- ast::GenericArg::LifetimeArg(_) => false,
- _ => true,
- })
- });
- if let Some(error_type_arg) = error_type_arg {
- if let Some(cap) = ctx.config.snippet_cap {
- edit.add_placeholder_snippet(cap, error_type_arg);
- }
- }
- },
- )
-}
-
-fn result_type(
- ctx: &AssistContext<'_>,
- core_result: &hir::Enum,
- ret_type: &ast::Type,
-) -> ast::Type {
- // Try to find a Result<T, ...> type alias in the current scope (shadowing the default).
- let result_path = hir::ModPath::from_segments(
- hir::PathKind::Plain,
- iter::once(hir::Name::new_symbol_root(hir::sym::Result.clone())),
- );
- let alias = ctx.sema.resolve_mod_path(ret_type.syntax(), &result_path).and_then(|def| {
- def.filter_map(|def| match def.as_module_def()? {
- hir::ModuleDef::TypeAlias(alias) => {
- let enum_ty = alias.ty(ctx.db()).as_adt()?.as_enum()?;
- (&enum_ty == core_result).then_some(alias)
- }
- _ => None,
- })
- .find_map(|alias| {
- let mut inserted_ret_type = false;
- let generic_params = alias
- .source(ctx.db())?
- .value
- .generic_param_list()?
- .generic_params()
- .map(|param| match param {
- // Replace the very first type parameter with the functions return type.
- ast::GenericParam::TypeParam(_) if !inserted_ret_type => {
- inserted_ret_type = true;
- ret_type.to_smolstr()
- }
- ast::GenericParam::LifetimeParam(_) => make::lifetime("'_").to_smolstr(),
- _ => make::ty_placeholder().to_smolstr(),
- })
- .join(", ");
-
- let name = alias.name(ctx.db());
- let name = name.as_str();
- Some(make::ty(&format!("{name}<{generic_params}>")))
- })
- });
- // If there is no applicable alias in scope use the default Result type.
- alias.unwrap_or_else(|| make::ext::ty_result(ret_type.clone(), make::ty_placeholder()))
-}
-
-fn tail_cb_impl(acc: &mut Vec<ast::Expr>, e: &ast::Expr) {
- match e {
- Expr::BreakExpr(break_expr) => {
- if let Some(break_expr_arg) = break_expr.expr() {
- for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(acc, e))
- }
- }
- Expr::ReturnExpr(_) => {
- // all return expressions have already been handled by the walk loop
- }
- e => acc.push(e.clone()),
- }
-}
-
-#[cfg(test)]
-mod tests {
- use crate::tests::{check_assist, check_assist_not_applicable};
-
- use super::*;
-
- #[test]
- fn wrap_return_type_in_result_simple() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() -> i3$02 {
- let test = "test";
- return 42i32;
-}
-"#,
- r#"
-fn foo() -> Result<i32, ${0:_}> {
- let test = "test";
- return Ok(42i32);
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_break_split_tail() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() -> i3$02 {
- loop {
- break if true {
- 1
- } else {
- 0
- };
- }
-}
-"#,
- r#"
-fn foo() -> Result<i32, ${0:_}> {
- loop {
- break if true {
- Ok(1)
- } else {
- Ok(0)
- };
- }
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_closure() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() {
- || -> i32$0 {
- let test = "test";
- return 42i32;
- };
-}
-"#,
- r#"
-fn foo() {
- || -> Result<i32, ${0:_}> {
- let test = "test";
- return Ok(42i32);
- };
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_return_type_bad_cursor() {
- check_assist_not_applicable(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() -> i32 {
- let test = "test";$0
- return 42i32;
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_return_type_bad_cursor_closure() {
- check_assist_not_applicable(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() {
- || -> i32 {
- let test = "test";$0
- return 42i32;
- };
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_closure_non_block() {
- check_assist_not_applicable(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() { || -> i$032 3; }
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_return_type_already_result_std() {
- check_assist_not_applicable(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() -> core::result::Result<i32$0, String> {
- let test = "test";
- return 42i32;
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_return_type_already_result() {
- cov_mark::check!(wrap_return_type_in_result_simple_return_type_already_result);
- check_assist_not_applicable(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() -> Result<i32$0, String> {
- let test = "test";
- return 42i32;
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_return_type_already_result_closure() {
- check_assist_not_applicable(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() {
- || -> Result<i32$0, String> {
- let test = "test";
- return 42i32;
- };
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_with_cursor() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() -> $0i32 {
- let test = "test";
- return 42i32;
-}
-"#,
- r#"
-fn foo() -> Result<i32, ${0:_}> {
- let test = "test";
- return Ok(42i32);
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_with_tail() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() ->$0 i32 {
- let test = "test";
- 42i32
-}
-"#,
- r#"
-fn foo() -> Result<i32, ${0:_}> {
- let test = "test";
- Ok(42i32)
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_with_tail_closure() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() {
- || ->$0 i32 {
- let test = "test";
- 42i32
- };
-}
-"#,
- r#"
-fn foo() {
- || -> Result<i32, ${0:_}> {
- let test = "test";
- Ok(42i32)
- };
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_with_tail_only() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() -> i32$0 { 42i32 }
-"#,
- r#"
-fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_with_tail_block_like() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() -> i32$0 {
- if true {
- 42i32
- } else {
- 24i32
- }
-}
-"#,
- r#"
-fn foo() -> Result<i32, ${0:_}> {
- if true {
- Ok(42i32)
- } else {
- Ok(24i32)
- }
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_without_block_closure() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() {
- || -> i32$0 {
- if true {
- 42i32
- } else {
- 24i32
- }
- };
-}
-"#,
- r#"
-fn foo() {
- || -> Result<i32, ${0:_}> {
- if true {
- Ok(42i32)
- } else {
- Ok(24i32)
- }
- };
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_with_nested_if() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() -> i32$0 {
- if true {
- if false {
- 1
- } else {
- 2
- }
- } else {
- 24i32
- }
-}
-"#,
- r#"
-fn foo() -> Result<i32, ${0:_}> {
- if true {
- if false {
- Ok(1)
- } else {
- Ok(2)
- }
- } else {
- Ok(24i32)
- }
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_with_await() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-async fn foo() -> i$032 {
- if true {
- if false {
- 1.await
- } else {
- 2.await
- }
- } else {
- 24i32.await
- }
-}
-"#,
- r#"
-async fn foo() -> Result<i32, ${0:_}> {
- if true {
- if false {
- Ok(1.await)
- } else {
- Ok(2.await)
- }
- } else {
- Ok(24i32.await)
- }
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_with_array() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() -> [i32;$0 3] { [1, 2, 3] }
-"#,
- r#"
-fn foo() -> Result<[i32; 3], ${0:_}> { Ok([1, 2, 3]) }
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_with_cast() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() -$0> i32 {
- if true {
- if false {
- 1 as i32
- } else {
- 2 as i32
- }
- } else {
- 24 as i32
- }
-}
-"#,
- r#"
-fn foo() -> Result<i32, ${0:_}> {
- if true {
- if false {
- Ok(1 as i32)
- } else {
- Ok(2 as i32)
- }
- } else {
- Ok(24 as i32)
- }
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_with_tail_block_like_match() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() -> i32$0 {
- let my_var = 5;
- match my_var {
- 5 => 42i32,
- _ => 24i32,
- }
-}
-"#,
- r#"
-fn foo() -> Result<i32, ${0:_}> {
- let my_var = 5;
- match my_var {
- 5 => Ok(42i32),
- _ => Ok(24i32),
- }
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_with_loop_with_tail() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() -> i32$0 {
- let my_var = 5;
- loop {
- println!("test");
- 5
- }
- my_var
-}
-"#,
- r#"
-fn foo() -> Result<i32, ${0:_}> {
- let my_var = 5;
- loop {
- println!("test");
- 5
- }
- Ok(my_var)
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_with_loop_in_let_stmt() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() -> i32$0 {
- let my_var = let x = loop {
- break 1;
- };
- my_var
-}
-"#,
- r#"
-fn foo() -> Result<i32, ${0:_}> {
- let my_var = let x = loop {
- break 1;
- };
- Ok(my_var)
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_with_tail_block_like_match_return_expr() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() -> i32$0 {
- let my_var = 5;
- let res = match my_var {
- 5 => 42i32,
- _ => return 24i32,
- };
- res
-}
-"#,
- r#"
-fn foo() -> Result<i32, ${0:_}> {
- let my_var = 5;
- let res = match my_var {
- 5 => 42i32,
- _ => return Ok(24i32),
- };
- Ok(res)
-}
-"#,
- );
-
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() -> i32$0 {
- let my_var = 5;
- let res = if my_var == 5 {
- 42i32
- } else {
- return 24i32;
- };
- res
-}
-"#,
- r#"
-fn foo() -> Result<i32, ${0:_}> {
- let my_var = 5;
- let res = if my_var == 5 {
- 42i32
- } else {
- return Ok(24i32);
- };
- Ok(res)
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_with_tail_block_like_match_deeper() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() -> i32$0 {
- let my_var = 5;
- match my_var {
- 5 => {
- if true {
- 42i32
- } else {
- 25i32
- }
- },
- _ => {
- let test = "test";
- if test == "test" {
- return bar();
- }
- 53i32
- },
- }
-}
-"#,
- r#"
-fn foo() -> Result<i32, ${0:_}> {
- let my_var = 5;
- match my_var {
- 5 => {
- if true {
- Ok(42i32)
- } else {
- Ok(25i32)
- }
- },
- _ => {
- let test = "test";
- if test == "test" {
- return Ok(bar());
- }
- Ok(53i32)
- },
- }
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_with_tail_block_like_early_return() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() -> i$032 {
- let test = "test";
- if test == "test" {
- return 24i32;
- }
- 53i32
-}
-"#,
- r#"
-fn foo() -> Result<i32, ${0:_}> {
- let test = "test";
- if test == "test" {
- return Ok(24i32);
- }
- Ok(53i32)
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_in_tail_position() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo(num: i32) -> $0i32 {
- return num
-}
-"#,
- r#"
-fn foo(num: i32) -> Result<i32, ${0:_}> {
- return Ok(num)
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_with_closure() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo(the_field: u32) ->$0 u32 {
- let true_closure = || { return true; };
- if the_field < 5 {
- let mut i = 0;
- if true_closure() {
- return 99;
- } else {
- return 0;
- }
- }
- the_field
-}
-"#,
- r#"
-fn foo(the_field: u32) -> Result<u32, ${0:_}> {
- let true_closure = || { return true; };
- if the_field < 5 {
- let mut i = 0;
- if true_closure() {
- return Ok(99);
- } else {
- return Ok(0);
- }
- }
- Ok(the_field)
-}
-"#,
- );
-
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo(the_field: u32) -> u32$0 {
- let true_closure = || {
- return true;
- };
- if the_field < 5 {
- let mut i = 0;
-
-
- if true_closure() {
- return 99;
- } else {
- return 0;
- }
- }
- let t = None;
-
- t.unwrap_or_else(|| the_field)
-}
-"#,
- r#"
-fn foo(the_field: u32) -> Result<u32, ${0:_}> {
- let true_closure = || {
- return true;
- };
- if the_field < 5 {
- let mut i = 0;
-
-
- if true_closure() {
- return Ok(99);
- } else {
- return Ok(0);
- }
- }
- let t = None;
-
- Ok(t.unwrap_or_else(|| the_field))
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_result_simple_with_weird_forms() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() -> i32$0 {
- let test = "test";
- if test == "test" {
- return 24i32;
- }
- let mut i = 0;
- loop {
- if i == 1 {
- break 55;
- }
- i += 1;
- }
-}
-"#,
- r#"
-fn foo() -> Result<i32, ${0:_}> {
- let test = "test";
- if test == "test" {
- return Ok(24i32);
- }
- let mut i = 0;
- loop {
- if i == 1 {
- break Ok(55);
- }
- i += 1;
- }
-}
-"#,
- );
-
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo(the_field: u32) -> u32$0 {
- if the_field < 5 {
- let mut i = 0;
- loop {
- if i > 5 {
- return 55u32;
- }
- i += 3;
- }
- match i {
- 5 => return 99,
- _ => return 0,
- };
- }
- the_field
-}
-"#,
- r#"
-fn foo(the_field: u32) -> Result<u32, ${0:_}> {
- if the_field < 5 {
- let mut i = 0;
- loop {
- if i > 5 {
- return Ok(55u32);
- }
- i += 3;
- }
- match i {
- 5 => return Ok(99),
- _ => return Ok(0),
- };
- }
- Ok(the_field)
-}
-"#,
- );
-
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo(the_field: u32) -> u3$02 {
- if the_field < 5 {
- let mut i = 0;
- match i {
- 5 => return 99,
- _ => return 0,
- }
- }
- the_field
-}
-"#,
- r#"
-fn foo(the_field: u32) -> Result<u32, ${0:_}> {
- if the_field < 5 {
- let mut i = 0;
- match i {
- 5 => return Ok(99),
- _ => return Ok(0),
- }
- }
- Ok(the_field)
-}
-"#,
- );
-
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo(the_field: u32) -> u32$0 {
- if the_field < 5 {
- let mut i = 0;
- if i == 5 {
- return 99
- } else {
- return 0
- }
- }
- the_field
-}
-"#,
- r#"
-fn foo(the_field: u32) -> Result<u32, ${0:_}> {
- if the_field < 5 {
- let mut i = 0;
- if i == 5 {
- return Ok(99)
- } else {
- return Ok(0)
- }
- }
- Ok(the_field)
-}
-"#,
- );
-
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo(the_field: u32) -> $0u32 {
- if the_field < 5 {
- let mut i = 0;
- if i == 5 {
- return 99;
- } else {
- return 0;
- }
- }
- the_field
-}
-"#,
- r#"
-fn foo(the_field: u32) -> Result<u32, ${0:_}> {
- if the_field < 5 {
- let mut i = 0;
- if i == 5 {
- return Ok(99);
- } else {
- return Ok(0);
- }
- }
- Ok(the_field)
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_local_result_type() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-type Result<T> = core::result::Result<T, ()>;
-
-fn foo() -> i3$02 {
- return 42i32;
-}
-"#,
- r#"
-type Result<T> = core::result::Result<T, ()>;
-
-fn foo() -> Result<i32> {
- return Ok(42i32);
-}
-"#,
- );
-
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-type Result2<T> = core::result::Result<T, ()>;
-
-fn foo() -> i3$02 {
- return 42i32;
-}
-"#,
- r#"
-type Result2<T> = core::result::Result<T, ()>;
-
-fn foo() -> Result<i32, ${0:_}> {
- return Ok(42i32);
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_imported_local_result_type() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-mod some_module {
- pub type Result<T> = core::result::Result<T, ()>;
-}
-
-use some_module::Result;
-
-fn foo() -> i3$02 {
- return 42i32;
-}
-"#,
- r#"
-mod some_module {
- pub type Result<T> = core::result::Result<T, ()>;
-}
-
-use some_module::Result;
-
-fn foo() -> Result<i32> {
- return Ok(42i32);
-}
-"#,
- );
-
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-mod some_module {
- pub type Result<T> = core::result::Result<T, ()>;
-}
-
-use some_module::*;
-
-fn foo() -> i3$02 {
- return 42i32;
-}
-"#,
- r#"
-mod some_module {
- pub type Result<T> = core::result::Result<T, ()>;
-}
-
-use some_module::*;
-
-fn foo() -> Result<i32> {
- return Ok(42i32);
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_local_result_type_from_function_body() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-fn foo() -> i3$02 {
- type Result<T> = core::result::Result<T, ()>;
- 0
-}
-"#,
- r#"
-fn foo() -> Result<i32, ${0:_}> {
- type Result<T> = core::result::Result<T, ()>;
- Ok(0)
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_local_result_type_already_using_alias() {
- check_assist_not_applicable(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-pub type Result<T> = core::result::Result<T, ()>;
-
-fn foo() -> Result<i3$02> {
- return Ok(42i32);
-}
-"#,
- );
- }
-
- #[test]
- fn wrap_return_type_in_local_result_type_multiple_generics() {
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-type Result<T, E> = core::result::Result<T, E>;
-
-fn foo() -> i3$02 {
- 0
-}
-"#,
- r#"
-type Result<T, E> = core::result::Result<T, E>;
-
-fn foo() -> Result<i32, ${0:_}> {
- Ok(0)
-}
-"#,
- );
-
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-type Result<T, E> = core::result::Result<Foo<T, E>, ()>;
-
-fn foo() -> i3$02 {
- 0
-}
- "#,
- r#"
-type Result<T, E> = core::result::Result<Foo<T, E>, ()>;
-
-fn foo() -> Result<i32, ${0:_}> {
- Ok(0)
-}
- "#,
- );
-
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-type Result<'a, T, E> = core::result::Result<Foo<T, E>, &'a ()>;
-
-fn foo() -> i3$02 {
- 0
-}
- "#,
- r#"
-type Result<'a, T, E> = core::result::Result<Foo<T, E>, &'a ()>;
-
-fn foo() -> Result<'_, i32, ${0:_}> {
- Ok(0)
-}
- "#,
- );
-
- check_assist(
- wrap_return_type_in_result,
- r#"
-//- minicore: result
-type Result<T, const N: usize> = core::result::Result<Foo<T>, Bar<N>>;
-
-fn foo() -> i3$02 {
- 0
-}
- "#,
- r#"
-type Result<T, const N: usize> = core::result::Result<Foo<T>, Bar<N>>;
-
-fn foo() -> Result<i32, ${0:_}> {
- Ok(0)
-}
- "#,
- );
- }
-}
diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs
index c98655b423..22620816d5 100644
--- a/crates/ide-assists/src/lib.rs
+++ b/crates/ide-assists/src/lib.rs
@@ -223,9 +223,9 @@ mod handlers {
mod unnecessary_async;
mod unqualify_method_call;
mod unwrap_block;
- mod unwrap_result_return_type;
+ mod unwrap_return_type;
mod unwrap_tuple;
- mod wrap_return_type_in_result;
+ mod wrap_return_type;
mod wrap_unwrap_cfg_attr;
pub(crate) fn all() -> &'static [Handler] {
@@ -355,10 +355,10 @@ mod handlers {
unmerge_use::unmerge_use,
unnecessary_async::unnecessary_async,
unwrap_block::unwrap_block,
- unwrap_result_return_type::unwrap_result_return_type,
+ unwrap_return_type::unwrap_return_type,
unwrap_tuple::unwrap_tuple,
unqualify_method_call::unqualify_method_call,
- wrap_return_type_in_result::wrap_return_type_in_result,
+ wrap_return_type::wrap_return_type,
wrap_unwrap_cfg_attr::wrap_unwrap_cfg_attr,
// These are manually sorted for better priorities. By default,
diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs
index 48e12a8107..933d45d750 100644
--- a/crates/ide-assists/src/tests/generated.rs
+++ b/crates/ide-assists/src/tests/generated.rs
@@ -3265,6 +3265,20 @@ fn foo() {
}
#[test]
+fn doctest_unwrap_option_return_type() {
+ check_doc_test(
+ "unwrap_option_return_type",
+ r#####"
+//- minicore: option
+fn foo() -> Option<i32>$0 { Some(42i32) }
+"#####,
+ r#####"
+fn foo() -> i32 { 42i32 }
+"#####,
+ )
+}
+
+#[test]
fn doctest_unwrap_result_return_type() {
check_doc_test(
"unwrap_result_return_type",
@@ -3298,6 +3312,20 @@ fn main() {
}
#[test]
+fn doctest_wrap_return_type_in_option() {
+ check_doc_test(
+ "wrap_return_type_in_option",
+ r#####"
+//- minicore: option
+fn foo() -> i32$0 { 42i32 }
+"#####,
+ r#####"
+fn foo() -> Option<i32> { Some(42i32) }
+"#####,
+ )
+}
+
+#[test]
fn doctest_wrap_return_type_in_result() {
check_doc_test(
"wrap_return_type_in_result",
diff --git a/crates/ide-completion/src/completions/item_list.rs b/crates/ide-completion/src/completions/item_list.rs
index 1883377408..3ab341e4ed 100644
--- a/crates/ide-completion/src/completions/item_list.rs
+++ b/crates/ide-completion/src/completions/item_list.rs
@@ -29,7 +29,9 @@ pub(crate) fn complete_item_list(
kind: &ItemListKind,
) {
let _p = tracing::info_span!("complete_item_list").entered();
- if path_ctx.is_trivial_path() {
+
+ // We handle completions for trait-impls in [`item_list::trait_impl`]
+ if path_ctx.is_trivial_path() && !matches!(kind, ItemListKind::TraitImpl(_)) {
add_keywords(acc, ctx, Some(kind));
}
@@ -75,73 +77,95 @@ fn add_keywords(acc: &mut Completions, ctx: &CompletionContext<'_>, kind: Option
let in_item_list = matches!(kind, Some(ItemListKind::SourceFile | ItemListKind::Module) | None);
let in_assoc_non_trait_impl = matches!(kind, Some(ItemListKind::Impl | ItemListKind::Trait));
- let in_extern_block = matches!(kind, Some(ItemListKind::ExternBlock));
+
+ let in_extern_block = matches!(kind, Some(ItemListKind::ExternBlock { .. }));
+ let in_unsafe_extern_block =
+ matches!(kind, Some(ItemListKind::ExternBlock { is_unsafe: true }));
+
let in_trait = matches!(kind, Some(ItemListKind::Trait));
- let in_trait_impl = matches!(kind, Some(ItemListKind::TraitImpl(_)));
let in_inherent_impl = matches!(kind, Some(ItemListKind::Impl));
- let no_vis_qualifiers = ctx.qualifier_ctx.vis_node.is_none();
let in_block = kind.is_none();
- let missing_qualifiers = [
- ctx.qualifier_ctx.unsafe_tok.is_none().then_some(("unsafe", "unsafe $0")),
- ctx.qualifier_ctx.async_tok.is_none().then_some(("async", "async $0")),
- ];
-
- if !in_trait_impl {
- // handle qualifier tokens
- if missing_qualifiers.iter().any(Option::is_none) {
- // only complete missing qualifiers
- missing_qualifiers.iter().filter_map(|x| *x).for_each(|(kw, snippet)| {
- add_keyword(kw, snippet);
- });
-
- if in_item_list || in_assoc_non_trait_impl {
- add_keyword("fn", "fn $1($2) {\n $0\n}");
- }
+ let no_vis_qualifiers = ctx.qualifier_ctx.vis_node.is_none();
+ let has_unsafe_kw = ctx.qualifier_ctx.unsafe_tok.is_some();
+ let has_async_kw = ctx.qualifier_ctx.async_tok.is_some();
+ let has_safe_kw = ctx.qualifier_ctx.safe_tok.is_some();
+
+ // Some keywords are invalid after non-vis qualifiers, so we handle them first.
+ if (has_unsafe_kw || has_safe_kw) && in_extern_block {
+ add_keyword("fn", "fn $1($2);");
+ add_keyword("static", "static $1: $2;");
+ return;
+ }
- if ctx.qualifier_ctx.unsafe_tok.is_some() && in_item_list {
- add_keyword("trait", "trait $1 {\n $0\n}");
- if no_vis_qualifiers {
- add_keyword("impl", "impl $1 {\n $0\n}");
- }
- }
+ if has_unsafe_kw || has_async_kw {
+ if !has_unsafe_kw {
+ add_keyword("unsafe", "unsafe $0");
+ }
+ if !has_async_kw {
+ add_keyword("async", "async $0");
+ }
- return;
+ if in_item_list || in_assoc_non_trait_impl {
+ add_keyword("fn", "fn $1($2) {\n $0\n}");
}
- if in_item_list {
- add_keyword("enum", "enum $1 {\n $0\n}");
- add_keyword("mod", "mod $0");
- add_keyword("static", "static $0");
- add_keyword("struct", "struct $0");
+ if has_unsafe_kw && in_item_list {
add_keyword("trait", "trait $1 {\n $0\n}");
- add_keyword("union", "union $1 {\n $0\n}");
- add_keyword("use", "use $0");
if no_vis_qualifiers {
add_keyword("impl", "impl $1 {\n $0\n}");
}
}
- if !in_trait && !in_block && no_vis_qualifiers {
- add_keyword("pub(crate)", "pub(crate) $0");
- add_keyword("pub(super)", "pub(super) $0");
- add_keyword("pub", "pub $0");
+ if !has_async_kw && no_vis_qualifiers && in_item_list {
+ add_keyword("extern", "extern $0");
}
- if in_extern_block {
- add_keyword("fn", "fn $1($2);");
- } else {
- if !in_inherent_impl {
- if !in_trait {
- add_keyword("extern", "extern $0");
- }
- add_keyword("type", "type $0");
- }
+ return;
+ }
- add_keyword("fn", "fn $1($2) {\n $0\n}");
- add_keyword("unsafe", "unsafe $0");
- add_keyword("const", "const $0");
- add_keyword("async", "async $0");
+ // ...and the rest deals with cases without any non-vis qualifiers.
+
+ // Visibility qualifiers
+ if !in_trait && !in_block && no_vis_qualifiers {
+ add_keyword("pub(crate)", "pub(crate) $0");
+ add_keyword("pub(super)", "pub(super) $0");
+ add_keyword("pub", "pub $0");
+ }
+
+ // Keywords that are valid in `item_list`
+ if in_item_list {
+ add_keyword("enum", "enum $1 {\n $0\n}");
+ add_keyword("mod", "mod $0");
+ add_keyword("static", "static $0");
+ add_keyword("struct", "struct $0");
+ add_keyword("trait", "trait $1 {\n $0\n}");
+ add_keyword("union", "union $1 {\n $0\n}");
+ add_keyword("use", "use $0");
+ if no_vis_qualifiers {
+ add_keyword("impl", "impl $1 {\n $0\n}");
+ }
+ }
+
+ if in_extern_block {
+ add_keyword("unsafe", "unsafe $0");
+ if in_unsafe_extern_block {
+ add_keyword("safe", "safe $0");
}
+
+ add_keyword("fn", "fn $1($2);");
+ add_keyword("static", "static $1: $2;");
+ } else {
+ if !in_inherent_impl {
+ if !in_trait {
+ add_keyword("extern", "extern $0");
+ }
+ add_keyword("type", "type $0");
+ }
+
+ add_keyword("fn", "fn $1($2) {\n $0\n}");
+ add_keyword("unsafe", "unsafe $0");
+ add_keyword("const", "const $0");
+ add_keyword("async", "async $0");
}
}
diff --git a/crates/ide-completion/src/completions/keyword.rs b/crates/ide-completion/src/completions/keyword.rs
index 0acb87872f..71ca6e9949 100644
--- a/crates/ide-completion/src/completions/keyword.rs
+++ b/crates/ide-completion/src/completions/keyword.rs
@@ -58,6 +58,7 @@ mod tests {
r"fn my_fn() { unsafe $0 }",
expect![[r#"
kw async
+ kw extern
kw fn
kw impl
kw trait
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index e49a9e3b06..0e1302ff2e 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -48,12 +48,16 @@ pub(crate) struct QualifierCtx {
// TODO: Add try_tok and default_tok
pub(crate) async_tok: Option<SyntaxToken>,
pub(crate) unsafe_tok: Option<SyntaxToken>,
+ pub(crate) safe_tok: Option<SyntaxToken>,
pub(crate) vis_node: Option<ast::Visibility>,
}
impl QualifierCtx {
pub(crate) fn none(&self) -> bool {
- self.async_tok.is_none() && self.unsafe_tok.is_none() && self.vis_node.is_none()
+ self.async_tok.is_none()
+ && self.unsafe_tok.is_none()
+ && self.safe_tok.is_none()
+ && self.vis_node.is_none()
}
}
@@ -229,7 +233,7 @@ pub(crate) enum ItemListKind {
Impl,
TraitImpl(Option<ast::Impl>),
Trait,
- ExternBlock,
+ ExternBlock { is_unsafe: bool },
}
#[derive(Debug)]
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index 1f9e3edf62..468ad81ad2 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -1108,7 +1108,14 @@ fn classify_name_ref(
},
None => return None,
} },
- ast::ExternItemList(_) => PathKind::Item { kind: ItemListKind::ExternBlock },
+ ast::ExternItemList(it) => {
+ let exn_blk = it.syntax().parent().and_then(ast::ExternBlock::cast);
+ PathKind::Item {
+ kind: ItemListKind::ExternBlock {
+ is_unsafe: exn_blk.and_then(|it| it.unsafe_token()).is_some(),
+ }
+ }
+ },
ast::SourceFile(_) => PathKind::Item { kind: ItemListKind::SourceFile },
_ => return None,
}
@@ -1310,6 +1317,7 @@ fn classify_name_ref(
match token.kind() {
SyntaxKind::UNSAFE_KW => qualifier_ctx.unsafe_tok = Some(token),
SyntaxKind::ASYNC_KW => qualifier_ctx.async_tok = Some(token),
+ SyntaxKind::SAFE_KW => qualifier_ctx.safe_tok = Some(token),
_ => {}
}
}
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index f2e9de9382..4dd171142f 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -1853,8 +1853,8 @@ fn f() { A { bar: b$0 }; }
expect![[r#"
fn bar() [type+name]
fn baz() [type]
- ex baz() [type]
ex bar() [type]
+ ex baz() [type]
st A []
fn f() []
"#]],
diff --git a/crates/ide-completion/src/tests/item_list.rs b/crates/ide-completion/src/tests/item_list.rs
index 532d4928ef..dfef8fa472 100644
--- a/crates/ide-completion/src/tests/item_list.rs
+++ b/crates/ide-completion/src/tests/item_list.rs
@@ -124,6 +124,7 @@ fn after_unsafe_token() {
r#"unsafe $0"#,
expect![[r#"
kw async
+ kw extern
kw fn
kw impl
kw trait
@@ -495,3 +496,57 @@ type O = $0;
",
)
}
+
+#[test]
+fn inside_extern_blocks() {
+ // Should suggest `fn`, `static`, `unsafe`
+ check(
+ r#"extern { $0 }"#,
+ expect![[r#"
+ ma makro!(…) macro_rules! makro
+ md module
+ kw crate::
+ kw fn
+ kw pub
+ kw pub(crate)
+ kw pub(super)
+ kw self::
+ kw static
+ kw unsafe
+ "#]],
+ );
+
+ // Should suggest `fn`, `static`, `safe`, `unsafe`
+ check(
+ r#"unsafe extern { $0 }"#,
+ expect![[r#"
+ ma makro!(…) macro_rules! makro
+ md module
+ kw crate::
+ kw fn
+ kw pub
+ kw pub(crate)
+ kw pub(super)
+ kw safe
+ kw self::
+ kw static
+ kw unsafe
+ "#]],
+ );
+
+ check(
+ r#"unsafe extern { pub safe $0 }"#,
+ expect![[r#"
+ kw fn
+ kw static
+ "#]],
+ );
+
+ check(
+ r#"unsafe extern { pub unsafe $0 }"#,
+ expect![[r#"
+ kw fn
+ kw static
+ "#]],
+ )
+}
diff --git a/crates/ide-completion/src/tests/pattern.rs b/crates/ide-completion/src/tests/pattern.rs
index bd3e7c72bc..a5eb0369b1 100644
--- a/crates/ide-completion/src/tests/pattern.rs
+++ b/crates/ide-completion/src/tests/pattern.rs
@@ -923,3 +923,21 @@ fn foo() {
"#]],
);
}
+
+#[test]
+fn private_item_in_module_in_function_body() {
+ check_empty(
+ r#"
+fn main() {
+ mod foo {
+ struct Private;
+ pub struct Public;
+ }
+ foo::$0
+}
+"#,
+ expect![[r#"
+ st Public Public
+ "#]],
+ );
+}
diff --git a/crates/ide-diagnostics/src/handlers/missing_unsafe.rs b/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
index 5b43f4b2af..44be53b87c 100644
--- a/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
@@ -595,4 +595,39 @@ unsafe fn foo(p: *mut i32) {
"#,
)
}
+
+ #[test]
+ fn no_unsafe_diagnostic_with_safe_kw() {
+ check_diagnostics(
+ r#"
+unsafe extern {
+ pub safe fn f();
+
+ pub unsafe fn g();
+
+ pub fn h();
+
+ pub safe static S1: i32;
+
+ pub unsafe static S2: i32;
+
+ pub static S3: i32;
+}
+
+fn main() {
+ f();
+ g();
+ //^^^💡 error: this operation is unsafe and requires an unsafe function or block
+ h();
+ //^^^💡 error: this operation is unsafe and requires an unsafe function or block
+
+ let _ = S1;
+ let _ = S2;
+ //^^💡 error: this operation is unsafe and requires an unsafe function or block
+ let _ = S3;
+ //^^💡 error: this operation is unsafe and requires an unsafe function or block
+}
+"#,
+ );
+ }
}
diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs
index 8e0166a4a7..121a463c9f 100644
--- a/crates/ide/src/annotations.rs
+++ b/crates/ide/src/annotations.rs
@@ -288,6 +288,20 @@ fn main() {
},
Annotation {
range: 53..57,
+ kind: HasReferences {
+ pos: FilePositionWrapper {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 53,
+ },
+ data: Some(
+ [],
+ ),
+ },
+ },
+ Annotation {
+ range: 53..57,
kind: Runnable(
Runnable {
use_name_in_title: false,
@@ -305,20 +319,6 @@ fn main() {
},
),
},
- Annotation {
- range: 53..57,
- kind: HasReferences {
- pos: FilePositionWrapper {
- file_id: FileId(
- 0,
- ),
- offset: 53,
- },
- data: Some(
- [],
- ),
- },
- },
]
"#]],
);
@@ -338,6 +338,20 @@ fn main() {
[
Annotation {
range: 7..11,
+ kind: HasImpls {
+ pos: FilePositionWrapper {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 7,
+ },
+ data: Some(
+ [],
+ ),
+ },
+ },
+ Annotation {
+ range: 7..11,
kind: HasReferences {
pos: FilePositionWrapper {
file_id: FileId(
@@ -358,13 +372,13 @@ fn main() {
},
},
Annotation {
- range: 7..11,
- kind: HasImpls {
+ range: 17..21,
+ kind: HasReferences {
pos: FilePositionWrapper {
file_id: FileId(
0,
),
- offset: 7,
+ offset: 17,
},
data: Some(
[],
@@ -390,20 +404,6 @@ fn main() {
},
),
},
- Annotation {
- range: 17..21,
- kind: HasReferences {
- pos: FilePositionWrapper {
- file_id: FileId(
- 0,
- ),
- offset: 17,
- },
- data: Some(
- [],
- ),
- },
- },
]
"#]],
);
@@ -427,7 +427,7 @@ fn main() {
[
Annotation {
range: 7..11,
- kind: HasReferences {
+ kind: HasImpls {
pos: FilePositionWrapper {
file_id: FileId(
0,
@@ -436,17 +436,14 @@ fn main() {
},
data: Some(
[
- FileRangeWrapper {
- file_id: FileId(
- 0,
- ),
- range: 57..61,
- },
- FileRangeWrapper {
+ NavigationTarget {
file_id: FileId(
0,
),
- range: 93..97,
+ full_range: 36..64,
+ focus_range: 57..61,
+ name: "impl",
+ kind: Impl,
},
],
),
@@ -454,7 +451,7 @@ fn main() {
},
Annotation {
range: 7..11,
- kind: HasImpls {
+ kind: HasReferences {
pos: FilePositionWrapper {
file_id: FileId(
0,
@@ -463,14 +460,17 @@ fn main() {
},
data: Some(
[
- NavigationTarget {
+ FileRangeWrapper {
file_id: FileId(
0,
),
- full_range: 36..64,
- focus_range: 57..61,
- name: "impl",
- kind: Impl,
+ range: 57..61,
+ },
+ FileRangeWrapper {
+ file_id: FileId(
+ 0,
+ ),
+ range: 93..97,
},
],
),
@@ -523,20 +523,6 @@ fn main() {
},
Annotation {
range: 69..73,
- kind: HasReferences {
- pos: FilePositionWrapper {
- file_id: FileId(
- 0,
- ),
- offset: 69,
- },
- data: Some(
- [],
- ),
- },
- },
- Annotation {
- range: 69..73,
kind: Runnable(
Runnable {
use_name_in_title: false,
@@ -554,6 +540,20 @@ fn main() {
},
),
},
+ Annotation {
+ range: 69..73,
+ kind: HasReferences {
+ pos: FilePositionWrapper {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 69,
+ },
+ data: Some(
+ [],
+ ),
+ },
+ },
]
"#]],
);
@@ -569,6 +569,20 @@ fn main() {}
[
Annotation {
range: 3..7,
+ kind: HasReferences {
+ pos: FilePositionWrapper {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 3,
+ },
+ data: Some(
+ [],
+ ),
+ },
+ },
+ Annotation {
+ range: 3..7,
kind: Runnable(
Runnable {
use_name_in_title: false,
@@ -586,20 +600,6 @@ fn main() {}
},
),
},
- Annotation {
- range: 3..7,
- kind: HasReferences {
- pos: FilePositionWrapper {
- file_id: FileId(
- 0,
- ),
- offset: 3,
- },
- data: Some(
- [],
- ),
- },
- },
]
"#]],
);
@@ -623,7 +623,7 @@ fn main() {
[
Annotation {
range: 7..11,
- kind: HasReferences {
+ kind: HasImpls {
pos: FilePositionWrapper {
file_id: FileId(
0,
@@ -632,17 +632,14 @@ fn main() {
},
data: Some(
[
- FileRangeWrapper {
- file_id: FileId(
- 0,
- ),
- range: 19..23,
- },
- FileRangeWrapper {
+ NavigationTarget {
file_id: FileId(
0,
),
- range: 74..78,
+ full_range: 14..56,
+ focus_range: 19..23,
+ name: "impl",
+ kind: Impl,
},
],
),
@@ -650,7 +647,7 @@ fn main() {
},
Annotation {
range: 7..11,
- kind: HasImpls {
+ kind: HasReferences {
pos: FilePositionWrapper {
file_id: FileId(
0,
@@ -659,14 +656,17 @@ fn main() {
},
data: Some(
[
- NavigationTarget {
+ FileRangeWrapper {
file_id: FileId(
0,
),
- full_range: 14..56,
- focus_range: 19..23,
- name: "impl",
- kind: Impl,
+ range: 19..23,
+ },
+ FileRangeWrapper {
+ file_id: FileId(
+ 0,
+ ),
+ range: 74..78,
},
],
),
@@ -695,20 +695,6 @@ fn main() {
},
Annotation {
range: 61..65,
- kind: HasReferences {
- pos: FilePositionWrapper {
- file_id: FileId(
- 0,
- ),
- offset: 61,
- },
- data: Some(
- [],
- ),
- },
- },
- Annotation {
- range: 61..65,
kind: Runnable(
Runnable {
use_name_in_title: false,
@@ -726,6 +712,20 @@ fn main() {
},
),
},
+ Annotation {
+ range: 61..65,
+ kind: HasReferences {
+ pos: FilePositionWrapper {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 61,
+ },
+ data: Some(
+ [],
+ ),
+ },
+ },
]
"#]],
);
@@ -746,20 +746,6 @@ mod tests {
[
Annotation {
range: 3..7,
- kind: HasReferences {
- pos: FilePositionWrapper {
- file_id: FileId(
- 0,
- ),
- offset: 3,
- },
- data: Some(
- [],
- ),
- },
- },
- Annotation {
- range: 3..7,
kind: Runnable(
Runnable {
use_name_in_title: false,
@@ -778,6 +764,20 @@ mod tests {
),
},
Annotation {
+ range: 3..7,
+ kind: HasReferences {
+ pos: FilePositionWrapper {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 3,
+ },
+ data: Some(
+ [],
+ ),
+ },
+ },
+ Annotation {
range: 18..23,
kind: Runnable(
Runnable {
@@ -876,7 +876,7 @@ struct Foo;
[
Annotation {
range: 0..71,
- kind: HasReferences {
+ kind: HasImpls {
pos: FilePositionWrapper {
file_id: FileId(
0,
@@ -890,7 +890,7 @@ struct Foo;
},
Annotation {
range: 0..71,
- kind: HasImpls {
+ kind: HasReferences {
pos: FilePositionWrapper {
file_id: FileId(
0,
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index c61b2ba84f..4cbcb6ed05 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -505,6 +505,44 @@ fn foo() {
}
#[test]
+ fn goto_def_in_included_file_inside_mod() {
+ check(
+ r#"
+//- minicore:include
+//- /main.rs
+mod a {
+ include!("b.rs");
+}
+//- /b.rs
+fn func_in_include() {
+ //^^^^^^^^^^^^^^^
+}
+fn foo() {
+ func_in_include$0();
+}
+"#,
+ );
+
+ check(
+ r#"
+//- minicore:include
+//- /main.rs
+mod a {
+ include!("a.rs");
+}
+//- /a.rs
+fn func_in_include() {
+ //^^^^^^^^^^^^^^^
+}
+
+fn foo() {
+ func_in_include$0();
+}
+"#,
+ );
+ }
+
+ #[test]
fn goto_def_if_items_same_name() {
check(
r#"
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index 64d717f88d..e7cb8a253f 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -2750,4 +2750,25 @@ impl Foo {
"#]],
);
}
+
+ #[test]
+ fn goto_ref_on_included_file() {
+ check(
+ r#"
+//- minicore:include
+//- /lib.rs
+include!("foo.rs");
+fn howdy() {
+ let _ = FOO;
+}
+//- /foo.rs
+const FOO$0: i32 = 0;
+"#,
+ expect![[r#"
+ FOO Const FileId(1) 0..19 6..9
+
+ FileId(0) 45..48
+ "#]],
+ );
+ }
}
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index 38dc522789..3bbbd36c1b 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -1350,18 +1350,18 @@ mod tests {
file_id: FileId(
0,
),
- full_range: 121..185,
- focus_range: 136..145,
- name: "foo2_test",
+ full_range: 52..115,
+ focus_range: 67..75,
+ name: "foo_test",
kind: Function,
},
NavigationTarget {
file_id: FileId(
0,
),
- full_range: 52..115,
- focus_range: 67..75,
- name: "foo_test",
+ full_range: 121..185,
+ focus_range: 136..145,
+ name: "foo2_test",
kind: Function,
},
]
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html b/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html
index 5d51b14978..a4449b5d8d 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html
@@ -46,14 +46,14 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
</style>
<pre><code><span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
- <span class="keyword">let</span> <span class="variable declaration reference" data-binding-hash="8384512769119783714" style="color: hsl(59,93%,58%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="semicolon">;</span>
- <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="17360984456076382725" style="color: hsl(95,79%,86%);">x</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="8384512769119783714" style="color: hsl(59,93%,58%);">hello</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
- <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="17186414787327620935" style="color: hsl(196,64%,89%);">y</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="8384512769119783714" style="color: hsl(59,93%,58%);">hello</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+ <span class="keyword">let</span> <span class="variable declaration reference" data-binding-hash="16711699953829236520" style="color: hsl(345,54%,46%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="semicolon">;</span>
+ <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="10753541418856619067" style="color: hsl(51,52%,47%);">x</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="16711699953829236520" style="color: hsl(345,54%,46%);">hello</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+ <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="9865812862466303869" style="color: hsl(329,86%,55%);">y</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="16711699953829236520" style="color: hsl(345,54%,46%);">hello</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
- <span class="keyword">let</span> <span class="variable declaration reference" data-binding-hash="4786021388930833562" style="color: hsl(137,61%,87%);">x</span> <span class="operator">=</span> <span class="string_literal">"other color please!"</span><span class="semicolon">;</span>
- <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="18017815841345165192" style="color: hsl(39,76%,89%);">y</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="4786021388930833562" style="color: hsl(137,61%,87%);">x</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+ <span class="keyword">let</span> <span class="variable declaration reference" data-binding-hash="4890670724659097491" style="color: hsl(330,46%,45%);">x</span> <span class="operator">=</span> <span class="string_literal">"other color please!"</span><span class="semicolon">;</span>
+ <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="4002942168268782293" style="color: hsl(114,87%,67%);">y</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="4890670724659097491" style="color: hsl(330,46%,45%);">x</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
<span class="brace">}</span>
<span class="keyword">fn</span> <span class="function declaration">bar</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
- <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable reference" data-binding-hash="8384512769119783714" style="color: hsl(59,93%,58%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="semicolon">;</span>
+ <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable reference" data-binding-hash="16711699953829236520" style="color: hsl(345,54%,46%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="semicolon">;</span>
<span class="brace">}</span></code></pre> \ No newline at end of file
diff --git a/crates/mbe/src/benchmark.rs b/crates/mbe/src/benchmark.rs
index 9e4ef14074..270bc05a4e 100644
--- a/crates/mbe/src/benchmark.rs
+++ b/crates/mbe/src/benchmark.rs
@@ -3,6 +3,7 @@
use intern::Symbol;
use rustc_hash::FxHashMap;
use span::{Edition, Span};
+use stdx::itertools::Itertools;
use syntax::{
ast::{self, HasName},
AstNode,
@@ -27,9 +28,10 @@ fn benchmark_parse_macro_rules() {
let hash: usize = {
let _pt = bench("mbe parse macro rules");
rules
- .values()
- .map(|it| {
- DeclarativeMacro::parse_macro_rules(it, |_| span::Edition::CURRENT).rules.len()
+ .into_iter()
+ .sorted_by_key(|(id, _)| id.clone())
+ .map(|(_, it)| {
+ DeclarativeMacro::parse_macro_rules(&it, |_| span::Edition::CURRENT).rules.len()
})
.sum()
};
@@ -55,12 +57,13 @@ fn benchmark_expand_macro_rules() {
})
.sum()
};
- assert_eq!(hash, 69413);
+ assert_eq!(hash, 65720);
}
fn macro_rules_fixtures() -> FxHashMap<String, DeclarativeMacro> {
macro_rules_fixtures_tt()
.into_iter()
+ .sorted_by_key(|(id, _)| id.clone())
.map(|(id, tt)| (id, DeclarativeMacro::parse_macro_rules(&tt, |_| span::Edition::CURRENT)))
.collect()
}
@@ -93,7 +96,7 @@ fn invocation_fixtures(
let mut seed = 123456789;
let mut res = Vec::new();
- for (name, it) in rules {
+ for (name, it) in rules.iter().sorted_by_key(|&(id, _)| id) {
for rule in it.rules.iter() {
// Generate twice
for _ in 0..2 {
diff --git a/crates/parser/src/grammar/items.rs b/crates/parser/src/grammar/items.rs
index 4e2a50d7a1..c4dce0daa5 100644
--- a/crates/parser/src/grammar/items.rs
+++ b/crates/parser/src/grammar/items.rs
@@ -135,6 +135,11 @@ pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> {
has_mods = true;
}
+ if p.at_contextual_kw(T![safe]) {
+ p.eat_contextual_kw(T![safe]);
+ has_mods = true;
+ }
+
if p.at(T![extern]) {
has_extern = true;
has_mods = true;
@@ -189,6 +194,7 @@ pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> {
T![fn] => fn_(p, m),
T![const] if p.nth(1) != T!['{'] => consts::konst(p, m),
+ T![static] if matches!(p.nth(1), IDENT | T![_] | T![mut]) => consts::static_(p, m),
T![trait] => traits::trait_(p, m),
T![impl] => traits::impl_(p, m),
diff --git a/crates/parser/src/syntax_kind/generated.rs b/crates/parser/src/syntax_kind/generated.rs
index 288a07ef44..8da338c0a2 100644
--- a/crates/parser/src/syntax_kind/generated.rs
+++ b/crates/parser/src/syntax_kind/generated.rs
@@ -136,6 +136,7 @@ pub enum SyntaxKind {
PURE_KW,
RAW_KW,
READONLY_KW,
+ SAFE_KW,
SYM_KW,
TRY_KW,
UNION_KW,
@@ -416,6 +417,7 @@ impl SyntaxKind {
PURE_KW => true,
RAW_KW => true,
READONLY_KW => true,
+ SAFE_KW => true,
SYM_KW => true,
UNION_KW => true,
YEET_KW => true,
@@ -503,6 +505,7 @@ impl SyntaxKind {
PURE_KW => true,
RAW_KW => true,
READONLY_KW => true,
+ SAFE_KW => true,
SYM_KW => true,
UNION_KW => true,
YEET_KW => true,
@@ -664,6 +667,7 @@ impl SyntaxKind {
"pure" => PURE_KW,
"raw" => RAW_KW,
"readonly" => READONLY_KW,
+ "safe" => SAFE_KW,
"sym" => SYM_KW,
"union" => UNION_KW,
"yeet" => YEET_KW,
@@ -707,4 +711,4 @@ impl SyntaxKind {
}
}
#[macro_export]
-macro_rules ! T { [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [Self] => { $ crate :: SyntaxKind :: SELF_TYPE_KW } ; [abstract] => { $ crate :: SyntaxKind :: ABSTRACT_KW } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [become] => { $ crate :: SyntaxKind :: BECOME_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [do] => { $ crate :: SyntaxKind :: DO_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [final] => { $ crate :: SyntaxKind :: FINAL_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [override] => { $ crate :: SyntaxKind :: OVERRIDE_KW } ; [priv] => { $ crate :: SyntaxKind :: PRIV_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [typeof] => { $ crate :: SyntaxKind :: TYPEOF_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [unsized] => { $ crate :: SyntaxKind :: UNSIZED_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [virtual] => { $ crate :: SyntaxKind :: VIRTUAL_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [yield] => { $ crate :: SyntaxKind :: YIELD_KW } ; [asm] => { $ crate :: SyntaxKind :: ASM_KW } ; [att_syntax] => { $ crate :: SyntaxKind :: ATT_SYNTAX_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [builtin] => { $ crate :: SyntaxKind :: BUILTIN_KW } ; [clobber_abi] => { $ crate :: SyntaxKind :: CLOBBER_ABI_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [format_args] => { $ crate :: SyntaxKind :: FORMAT_ARGS_KW } ; [inlateout] => { $ crate :: SyntaxKind :: INLATEOUT_KW } ; [inout] => { $ crate :: SyntaxKind :: INOUT_KW } ; [label] => { $ crate :: SyntaxKind :: LABEL_KW } ; [lateout] => { $ crate :: SyntaxKind :: LATEOUT_KW } ; [macro_rules] => { $ crate :: SyntaxKind :: MACRO_RULES_KW } ; [may_unwind] => { $ crate :: SyntaxKind :: MAY_UNWIND_KW } ; [nomem] => { $ crate :: SyntaxKind :: NOMEM_KW } ; [noreturn] => { $ crate :: SyntaxKind :: NORETURN_KW } ; [nostack] => { $ crate :: SyntaxKind :: NOSTACK_KW } ; [offset_of] => { $ crate :: SyntaxKind :: OFFSET_OF_KW } ; [options] => { $ crate :: SyntaxKind :: OPTIONS_KW } ; [out] => { $ crate :: SyntaxKind :: OUT_KW } ; [preserves_flags] => { $ crate :: SyntaxKind :: PRESERVES_FLAGS_KW } ; [pure] => { $ crate :: SyntaxKind :: PURE_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [readonly] => { $ crate :: SyntaxKind :: READONLY_KW } ; [sym] => { $ crate :: SyntaxKind :: SYM_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [yeet] => { $ crate :: SyntaxKind :: YEET_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [gen] => { $ crate :: SyntaxKind :: GEN_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [int_number] => { $ crate :: SyntaxKind :: INT_NUMBER } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [string] => { $ crate :: SyntaxKind :: STRING } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; }
+macro_rules ! T { [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [Self] => { $ crate :: SyntaxKind :: SELF_TYPE_KW } ; [abstract] => { $ crate :: SyntaxKind :: ABSTRACT_KW } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [become] => { $ crate :: SyntaxKind :: BECOME_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [do] => { $ crate :: SyntaxKind :: DO_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [final] => { $ crate :: SyntaxKind :: FINAL_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [override] => { $ crate :: SyntaxKind :: OVERRIDE_KW } ; [priv] => { $ crate :: SyntaxKind :: PRIV_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [typeof] => { $ crate :: SyntaxKind :: TYPEOF_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [unsized] => { $ crate :: SyntaxKind :: UNSIZED_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [virtual] => { $ crate :: SyntaxKind :: VIRTUAL_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [yield] => { $ crate :: SyntaxKind :: YIELD_KW } ; [asm] => { $ crate :: SyntaxKind :: ASM_KW } ; [att_syntax] => { $ crate :: SyntaxKind :: ATT_SYNTAX_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [builtin] => { $ crate :: SyntaxKind :: BUILTIN_KW } ; [clobber_abi] => { $ crate :: SyntaxKind :: CLOBBER_ABI_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [format_args] => { $ crate :: SyntaxKind :: FORMAT_ARGS_KW } ; [inlateout] => { $ crate :: SyntaxKind :: INLATEOUT_KW } ; [inout] => { $ crate :: SyntaxKind :: INOUT_KW } ; [label] => { $ crate :: SyntaxKind :: LABEL_KW } ; [lateout] => { $ crate :: SyntaxKind :: LATEOUT_KW } ; [macro_rules] => { $ crate :: SyntaxKind :: MACRO_RULES_KW } ; [may_unwind] => { $ crate :: SyntaxKind :: MAY_UNWIND_KW } ; [nomem] => { $ crate :: SyntaxKind :: NOMEM_KW } ; [noreturn] => { $ crate :: SyntaxKind :: NORETURN_KW } ; [nostack] => { $ crate :: SyntaxKind :: NOSTACK_KW } ; [offset_of] => { $ crate :: SyntaxKind :: OFFSET_OF_KW } ; [options] => { $ crate :: SyntaxKind :: OPTIONS_KW } ; [out] => { $ crate :: SyntaxKind :: OUT_KW } ; [preserves_flags] => { $ crate :: SyntaxKind :: PRESERVES_FLAGS_KW } ; [pure] => { $ crate :: SyntaxKind :: PURE_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [readonly] => { $ crate :: SyntaxKind :: READONLY_KW } ; [safe] => { $ crate :: SyntaxKind :: SAFE_KW } ; [sym] => { $ crate :: SyntaxKind :: SYM_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [yeet] => { $ crate :: SyntaxKind :: YEET_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [gen] => { $ crate :: SyntaxKind :: GEN_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [int_number] => { $ crate :: SyntaxKind :: INT_NUMBER } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [string] => { $ crate :: SyntaxKind :: STRING } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; }
diff --git a/crates/parser/test_data/parser/ok/0073_safe_declarations_in_extern_blocks.rast b/crates/parser/test_data/parser/ok/0073_safe_declarations_in_extern_blocks.rast
new file mode 100644
index 0000000000..b3d9e55806
--- /dev/null
+++ b/crates/parser/test_data/parser/ok/0073_safe_declarations_in_extern_blocks.rast
@@ -0,0 +1,208 @@
+SOURCE_FILE
+ EXTERN_BLOCK
+ UNSAFE_KW "unsafe"
+ WHITESPACE " "
+ ABI
+ EXTERN_KW "extern"
+ WHITESPACE " "
+ EXTERN_ITEM_LIST
+ L_CURLY "{"
+ WHITESPACE "\n "
+ FN
+ COMMENT "// sqrt (from libm) may be called with any `f64`"
+ WHITESPACE "\n "
+ VISIBILITY
+ PUB_KW "pub"
+ WHITESPACE " "
+ SAFE_KW "safe"
+ WHITESPACE " "
+ FN_KW "fn"
+ WHITESPACE " "
+ NAME
+ IDENT "sqrt"
+ PARAM_LIST
+ L_PAREN "("
+ PARAM
+ IDENT_PAT
+ NAME
+ IDENT "x"
+ COLON ":"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "f64"
+ R_PAREN ")"
+ WHITESPACE " "
+ RET_TYPE
+ THIN_ARROW "->"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "f64"
+ SEMICOLON ";"
+ WHITESPACE "\n\n "
+ FN
+ COMMENT "// strlen (from libc) requires a valid pointer,"
+ WHITESPACE "\n "
+ COMMENT "// so we mark it as being an unsafe fn"
+ WHITESPACE "\n "
+ VISIBILITY
+ PUB_KW "pub"
+ WHITESPACE " "
+ UNSAFE_KW "unsafe"
+ WHITESPACE " "
+ FN_KW "fn"
+ WHITESPACE " "
+ NAME
+ IDENT "strlen"
+ PARAM_LIST
+ L_PAREN "("
+ PARAM
+ IDENT_PAT
+ NAME
+ IDENT "p"
+ COLON ":"
+ WHITESPACE " "
+ PTR_TYPE
+ STAR "*"
+ CONST_KW "const"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "c_char"
+ R_PAREN ")"
+ WHITESPACE " "
+ RET_TYPE
+ THIN_ARROW "->"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "usize"
+ SEMICOLON ";"
+ WHITESPACE "\n\n "
+ FN
+ COMMENT "// this function doesn't say safe or unsafe, so it defaults to unsafe"
+ WHITESPACE "\n "
+ VISIBILITY
+ PUB_KW "pub"
+ WHITESPACE " "
+ FN_KW "fn"
+ WHITESPACE " "
+ NAME
+ IDENT "free"
+ PARAM_LIST
+ L_PAREN "("
+ PARAM
+ IDENT_PAT
+ NAME
+ IDENT "p"
+ COLON ":"
+ WHITESPACE " "
+ PTR_TYPE
+ STAR "*"
+ MUT_KW "mut"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "core"
+ COLON2 "::"
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "ffi"
+ COLON2 "::"
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "c_void"
+ R_PAREN ")"
+ SEMICOLON ";"
+ WHITESPACE "\n\n "
+ STATIC
+ VISIBILITY
+ PUB_KW "pub"
+ WHITESPACE " "
+ SAFE_KW "safe"
+ WHITESPACE " "
+ STATIC_KW "static"
+ WHITESPACE " "
+ MUT_KW "mut"
+ WHITESPACE " "
+ NAME
+ IDENT "COUNTER"
+ COLON ":"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "i32"
+ SEMICOLON ";"
+ WHITESPACE "\n\n "
+ STATIC
+ VISIBILITY
+ PUB_KW "pub"
+ WHITESPACE " "
+ UNSAFE_KW "unsafe"
+ WHITESPACE " "
+ STATIC_KW "static"
+ WHITESPACE " "
+ NAME
+ IDENT "IMPORTANT_BYTES"
+ COLON ":"
+ WHITESPACE " "
+ ARRAY_TYPE
+ L_BRACK "["
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "u8"
+ SEMICOLON ";"
+ WHITESPACE " "
+ CONST_ARG
+ LITERAL
+ INT_NUMBER "256"
+ R_BRACK "]"
+ SEMICOLON ";"
+ WHITESPACE "\n\n "
+ STATIC
+ VISIBILITY
+ PUB_KW "pub"
+ WHITESPACE " "
+ SAFE_KW "safe"
+ WHITESPACE " "
+ STATIC_KW "static"
+ WHITESPACE " "
+ NAME
+ IDENT "LINES"
+ COLON ":"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "SyncUnsafeCell"
+ GENERIC_ARG_LIST
+ L_ANGLE "<"
+ TYPE_ARG
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "i32"
+ R_ANGLE ">"
+ SEMICOLON ";"
+ WHITESPACE "\n"
+ R_CURLY "}"
+ WHITESPACE "\n"
diff --git a/crates/parser/test_data/parser/ok/0073_safe_declarations_in_extern_blocks.rs b/crates/parser/test_data/parser/ok/0073_safe_declarations_in_extern_blocks.rs
new file mode 100644
index 0000000000..267a128649
--- /dev/null
+++ b/crates/parser/test_data/parser/ok/0073_safe_declarations_in_extern_blocks.rs
@@ -0,0 +1,17 @@
+unsafe extern {
+ // sqrt (from libm) may be called with any `f64`
+ pub safe fn sqrt(x: f64) -> f64;
+
+ // strlen (from libc) requires a valid pointer,
+ // so we mark it as being an unsafe fn
+ pub unsafe fn strlen(p: *const c_char) -> usize;
+
+ // this function doesn't say safe or unsafe, so it defaults to unsafe
+ pub fn free(p: *mut core::ffi::c_void);
+
+ pub safe static mut COUNTER: i32;
+
+ pub unsafe static IMPORTANT_BYTES: [u8; 256];
+
+ pub safe static LINES: SyncUnsafeCell<i32>;
+}
diff --git a/crates/project-model/src/tests.rs b/crates/project-model/src/tests.rs
index 5099697a69..ef115494a8 100644
--- a/crates/project-model/src/tests.rs
+++ b/crates/project-model/src/tests.rs
@@ -222,8 +222,6 @@ fn rust_project_is_proc_macro_has_proc_macro_dep() {
}
#[test]
-// FIXME Remove the ignore
-#[ignore = "requires nightly until the sysroot ships a cargo workspace for library on stable"]
fn smoke_test_real_sysroot_cargo() {
let file_map = &mut FxHashMap::<AbsPathBuf, FileId>::default();
let meta: Metadata = get_test_json_file("hello-world-metadata.json");
@@ -235,7 +233,6 @@ fn smoke_test_real_sysroot_cargo() {
&Default::default(),
);
assert!(matches!(sysroot.mode(), SysrootMode::Workspace(_)));
-
let project_workspace = ProjectWorkspace {
kind: ProjectWorkspaceKind::Cargo {
cargo: cargo_workspace,
diff --git a/crates/ra-salsa/Cargo.toml b/crates/ra-salsa/Cargo.toml
index b81e780337..f8a3156fe4 100644
--- a/crates/ra-salsa/Cargo.toml
+++ b/crates/ra-salsa/Cargo.toml
@@ -17,7 +17,7 @@ indexmap = "2.1.0"
lock_api = "0.4"
tracing = "0.1"
parking_lot = "0.12.1"
-rustc-hash = "1.0"
+rustc-hash = "2.0.0"
smallvec = "1.0.0"
oorandom = "11"
triomphe = "0.1.11"
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index c216461427..51c81a0d1a 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -6,6 +6,7 @@ use std::{
time::{SystemTime, UNIX_EPOCH},
};
+use cfg::{CfgAtom, CfgDiff};
use hir::{
db::{DefDatabase, ExpandDatabase, HirDatabase},
Adt, AssocItem, Crate, DefWithBody, HasSource, HirDisplay, HirFileIdExt, ImportPathConfig,
@@ -31,7 +32,7 @@ use itertools::Itertools;
use load_cargo::{load_workspace, LoadCargoConfig, ProcMacroServerChoice};
use oorandom::Rand32;
use profile::{Bytes, StopWatch};
-use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustLibSource};
+use project_model::{CargoConfig, CfgOverrides, ProjectManifest, ProjectWorkspace, RustLibSource};
use rayon::prelude::*;
use rustc_hash::{FxHashMap, FxHashSet};
use syntax::{AstNode, SyntaxNode};
@@ -65,7 +66,11 @@ impl flags::AnalysisStats {
false => Some(RustLibSource::Discover),
},
all_targets: true,
- set_test: true,
+ set_test: !self.no_test,
+ cfg_overrides: CfgOverrides {
+ global: CfgDiff::new(vec![CfgAtom::Flag(hir::sym::miri.clone())], vec![]).unwrap(),
+ selective: Default::default(),
+ },
..Default::default()
};
let no_progress = &|_| ();
diff --git a/crates/rust-analyzer/src/cli/flags.rs b/crates/rust-analyzer/src/cli/flags.rs
index 60d621b214..ff24602144 100644
--- a/crates/rust-analyzer/src/cli/flags.rs
+++ b/crates/rust-analyzer/src/cli/flags.rs
@@ -71,6 +71,8 @@ xflags::xflags! {
optional --with-deps
/// Don't load sysroot crates (`std`, `core` & friends).
optional --no-sysroot
+ /// Don't set #[cfg(test)].
+ optional --no-test
/// Don't run build scripts or load `OUT_DIR` values by running `cargo check` before analysis.
optional --disable-build-scripts
@@ -233,6 +235,7 @@ pub struct AnalysisStats {
pub only: Option<String>,
pub with_deps: bool,
pub no_sysroot: bool,
+ pub no_test: bool,
pub disable_build_scripts: bool,
pub disable_proc_macros: bool,
pub proc_macro_srv: Option<PathBuf>,
diff --git a/crates/rust-analyzer/src/lsp/from_proto.rs b/crates/rust-analyzer/src/lsp/from_proto.rs
index 1f4544887f..47e9961cf1 100644
--- a/crates/rust-analyzer/src/lsp/from_proto.rs
+++ b/crates/rust-analyzer/src/lsp/from_proto.rs
@@ -35,10 +35,18 @@ pub(crate) fn offset(
.ok_or_else(|| format_err!("Invalid wide col offset"))?
}
};
- let text_size = line_index.index.offset(line_col).ok_or_else(|| {
+ let line_range = line_index.index.line(line_col.line).ok_or_else(|| {
format_err!("Invalid offset {line_col:?} (line index length: {:?})", line_index.index.len())
})?;
- Ok(text_size)
+ let col = TextSize::from(line_col.col);
+ let clamped_len = col.min(line_range.len());
+ if clamped_len < col {
+ tracing::error!(
+ "Position {line_col:?} column exceeds line length {}, clamping it",
+ u32::from(line_range.len()),
+ );
+ }
+ Ok(line_range.start() + clamped_len)
}
pub(crate) fn text_range(
diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram
index 52ad439e4d..90441c27f6 100644
--- a/crates/syntax/rust.ungram
+++ b/crates/syntax/rust.ungram
@@ -190,7 +190,7 @@ UseTreeList =
Fn =
Attr* Visibility?
- 'default'? 'const'? 'async'? 'gen'? 'unsafe'? Abi?
+ 'default'? 'const'? 'async'? 'gen'? 'unsafe'? 'safe'? Abi?
'fn' Name GenericParamList? ParamList RetType? WhereClause?
(body:BlockExpr | ';')
@@ -284,6 +284,7 @@ Const =
Static =
Attr* Visibility?
+ 'unsafe'? 'safe'?
'static' 'mut'? Name ':' Type
('=' body:Expr)? ';'
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index c81a19f3bd..4f8bff489c 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -668,6 +668,8 @@ impl Fn {
#[inline]
pub fn gen_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![gen]) }
#[inline]
+ pub fn safe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![safe]) }
+ #[inline]
pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
}
@@ -1761,7 +1763,11 @@ impl Static {
#[inline]
pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
#[inline]
+ pub fn safe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![safe]) }
+ #[inline]
pub fn static_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![static]) }
+ #[inline]
+ pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
diff --git a/crates/syntax/src/ptr.rs b/crates/syntax/src/ptr.rs
index ed4894f9b9..11b79e4e0e 100644
--- a/crates/syntax/src/ptr.rs
+++ b/crates/syntax/src/ptr.rs
@@ -27,7 +27,7 @@ pub struct AstPtr<N: AstNode> {
_ty: PhantomData<fn() -> N>,
}
-impl<N: AstNode + std::fmt::Debug> std::fmt::Debug for AstPtr<N> {
+impl<N: AstNode> std::fmt::Debug for AstPtr<N> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("AstPtr").field(&self.raw).finish()
}
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index babeb4272b..463718835b 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -95,8 +95,8 @@ avoid checking unnecessary things.
Default:
----
{
- "debug_assertions": null,
- "miri": null
+ "miri": null,
+ "debug_assertions": null
}
----
List of cfg options to enable with the given values.
@@ -321,18 +321,10 @@ Enables completions of private items and fields that are defined in the current
Default:
----
{
- "Arc::new": {
- "postfix": "arc",
- "body": "Arc::new(${receiver})",
- "requires": "std::sync::Arc",
- "description": "Put the expression into an `Arc`",
- "scope": "expr"
- },
- "Rc::new": {
- "postfix": "rc",
- "body": "Rc::new(${receiver})",
- "requires": "std::rc::Rc",
- "description": "Put the expression into an `Rc`",
+ "Ok": {
+ "postfix": "ok",
+ "body": "Ok(${receiver})",
+ "description": "Wrap the expression in a `Result::Ok`",
"scope": "expr"
},
"Box::pin": {
@@ -342,10 +334,11 @@ Default:
"description": "Put the expression into a pinned `Box`",
"scope": "expr"
},
- "Err": {
- "postfix": "err",
- "body": "Err(${receiver})",
- "description": "Wrap the expression in a `Result::Err`",
+ "Arc::new": {
+ "postfix": "arc",
+ "body": "Arc::new(${receiver})",
+ "requires": "std::sync::Arc",
+ "description": "Put the expression into an `Arc`",
"scope": "expr"
},
"Some": {
@@ -354,10 +347,17 @@ Default:
"description": "Wrap the expression in an `Option::Some`",
"scope": "expr"
},
- "Ok": {
- "postfix": "ok",
- "body": "Ok(${receiver})",
- "description": "Wrap the expression in a `Result::Ok`",
+ "Err": {
+ "postfix": "err",
+ "body": "Err(${receiver})",
+ "description": "Wrap the expression in a `Result::Err`",
+ "scope": "expr"
+ },
+ "Rc::new": {
+ "postfix": "rc",
+ "body": "Rc::new(${receiver})",
+ "requires": "std::rc::Rc",
+ "description": "Put the expression into an `Rc`",
"scope": "expr"
}
}
diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json
index 7de7576317..10b633511d 100644
--- a/editors/code/package-lock.json
+++ b/editors/code/package-lock.json
@@ -22,14 +22,14 @@
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"@vscode/test-electron": "^2.3.8",
- "@vscode/vsce": "^2.19.0",
+ "@vscode/vsce": "^3.0.0",
"esbuild": "^0.18.12",
"eslint": "^8.44.0",
"eslint-config-prettier": "^8.8.0",
"ovsx": "^0.8.2",
"prettier": "^3.0.0",
"tslib": "^2.6.0",
- "typescript": "^5.1.6"
+ "typescript": "^5.6.0"
},
"engines": {
"vscode": "^1.78.0"
@@ -44,6 +44,218 @@
"node": ">=0.10.0"
}
},
+ "node_modules/@azure/abort-controller": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz",
+ "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/core-auth": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.9.0.tgz",
+ "integrity": "sha512-FPwHpZywuyasDSLMqJ6fhbOK3TqUdviZNF8OqRGA4W5Ewib2lEEZ+pBsYcBa88B2NGO/SEnYPGhyBqNlE8ilSw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@azure/abort-controller": "^2.0.0",
+ "@azure/core-util": "^1.11.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/core-client": {
+ "version": "1.9.2",
+ "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.9.2.tgz",
+ "integrity": "sha512-kRdry/rav3fUKHl/aDLd/pDLcB+4pOFwPPTVEExuMyaI5r+JBbMWqRbCY1pn5BniDaU3lRxO9eaQ1AmSMehl/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@azure/abort-controller": "^2.0.0",
+ "@azure/core-auth": "^1.4.0",
+ "@azure/core-rest-pipeline": "^1.9.1",
+ "@azure/core-tracing": "^1.0.0",
+ "@azure/core-util": "^1.6.1",
+ "@azure/logger": "^1.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/core-rest-pipeline": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.17.0.tgz",
+ "integrity": "sha512-62Vv8nC+uPId3j86XJ0WI+sBf0jlqTqPUFCBNrGtlaUeQUIXWV/D8GE5A1d+Qx8H7OQojn2WguC8kChD6v0shA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@azure/abort-controller": "^2.0.0",
+ "@azure/core-auth": "^1.8.0",
+ "@azure/core-tracing": "^1.0.1",
+ "@azure/core-util": "^1.9.0",
+ "@azure/logger": "^1.0.0",
+ "http-proxy-agent": "^7.0.0",
+ "https-proxy-agent": "^7.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/core-rest-pipeline/node_modules/agent-base": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
+ "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/@azure/core-rest-pipeline/node_modules/http-proxy-agent": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/@azure/core-rest-pipeline/node_modules/https-proxy-agent": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
+ "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.0.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/@azure/core-tracing": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.2.0.tgz",
+ "integrity": "sha512-UKTiEJPkWcESPYJz3X5uKRYyOcJD+4nYph+KpfdPRnQJVrZfk0KJgdnaAWKfhsBBtAf/D58Az4AvCJEmWgIBAg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/core-util": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.11.0.tgz",
+ "integrity": "sha512-DxOSLua+NdpWoSqULhjDyAZTXFdP/LKkqtYuxxz1SCN289zk3OG8UOpnCQAz/tygyACBtWp/BoO72ptK7msY8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@azure/abort-controller": "^2.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/identity": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.5.0.tgz",
+ "integrity": "sha512-EknvVmtBuSIic47xkOqyNabAme0RYTw52BTMz8eBgU1ysTyMrD1uOoM+JdS0J/4Yfp98IBT3osqq3BfwSaNaGQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@azure/abort-controller": "^2.0.0",
+ "@azure/core-auth": "^1.9.0",
+ "@azure/core-client": "^1.9.2",
+ "@azure/core-rest-pipeline": "^1.17.0",
+ "@azure/core-tracing": "^1.0.0",
+ "@azure/core-util": "^1.11.0",
+ "@azure/logger": "^1.0.0",
+ "@azure/msal-browser": "^3.26.1",
+ "@azure/msal-node": "^2.15.0",
+ "events": "^3.0.0",
+ "jws": "^4.0.0",
+ "open": "^8.0.0",
+ "stoppable": "^1.1.0",
+ "tslib": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/logger": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.1.4.tgz",
+ "integrity": "sha512-4IXXzcCdLdlXuCG+8UKEwLA1T1NHqUfanhXYHiQTn+6sfWCZXduqbtXDGceg3Ce5QxTGo7EqmbV6Bi+aqKuClQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@azure/msal-browser": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.26.1.tgz",
+ "integrity": "sha512-y78sr9g61aCAH9fcLO1um+oHFXc1/5Ap88RIsUSuzkm0BHzFnN+PXGaQeuM1h5Qf5dTnWNOd6JqkskkMPAhh7Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@azure/msal-common": "14.15.0"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/@azure/msal-common": {
+ "version": "14.15.0",
+ "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.15.0.tgz",
+ "integrity": "sha512-ImAQHxmpMneJ/4S8BRFhjt1MZ3bppmpRPYYNyzeQPeFN288YKbb8TmmISQEbtfkQ1BPASvYZU5doIZOPBAqENQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/@azure/msal-node": {
+ "version": "2.15.0",
+ "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.15.0.tgz",
+ "integrity": "sha512-gVPW8YLz92ZeCibQH2QUw96odJoiM3k/ZPH3f2HxptozmH6+OnyyvKXo/Egg39HAM230akarQKHf0W74UHlh0Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@azure/msal-common": "14.15.0",
+ "jsonwebtoken": "^9.0.0",
+ "uuid": "^8.3.0"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
"node_modules/@esbuild/android-arm": {
"version": "0.18.12",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.12.tgz",
@@ -496,6 +708,109 @@
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
"dev": true
},
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@isaacs/cliui/node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -778,26 +1093,31 @@
}
},
"node_modules/@vscode/vsce": {
- "version": "2.19.0",
- "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.19.0.tgz",
- "integrity": "sha512-dAlILxC5ggOutcvJY24jxz913wimGiUrHaPkk16Gm9/PGFbz1YezWtrXsTKUtJws4fIlpX2UIlVlVESWq8lkfQ==",
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-3.1.1.tgz",
+ "integrity": "sha512-N62Ca9ElRPLUUzf7l9CeEBlLrYzFPRQq7huKk4pVW+LjIOSXfFIPudixn5QvZcz+yXDOh15IopI3K2o3y9666Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "azure-devops-node-api": "^11.0.1",
+ "@azure/identity": "^4.1.0",
+ "@vscode/vsce-sign": "^2.0.0",
+ "azure-devops-node-api": "^12.5.0",
"chalk": "^2.4.2",
"cheerio": "^1.0.0-rc.9",
- "commander": "^6.1.0",
- "glob": "^7.0.6",
+ "cockatiel": "^3.1.2",
+ "commander": "^6.2.1",
+ "form-data": "^4.0.0",
+ "glob": "^11.0.0",
"hosted-git-info": "^4.0.2",
"jsonc-parser": "^3.2.0",
"leven": "^3.1.0",
- "markdown-it": "^12.3.2",
+ "markdown-it": "^14.1.0",
"mime": "^1.3.4",
"minimatch": "^3.0.3",
"parse-semver": "^1.1.1",
"read": "^1.0.7",
- "semver": "^5.1.0",
- "tmp": "^0.2.1",
+ "semver": "^7.5.2",
+ "tmp": "^0.2.3",
"typed-rest-client": "^1.8.4",
"url-join": "^4.0.1",
"xml2js": "^0.5.0",
@@ -808,12 +1128,157 @@
"vsce": "vsce"
},
"engines": {
- "node": ">= 14"
+ "node": ">= 20"
},
"optionalDependencies": {
"keytar": "^7.7.0"
}
},
+ "node_modules/@vscode/vsce-sign": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@vscode/vsce-sign/-/vsce-sign-2.0.4.tgz",
+ "integrity": "sha512-0uL32egStKYfy60IqnynAChMTbL0oqpqk0Ew0YHiIb+fayuGZWADuIPHWUcY1GCnAA+VgchOPDMxnc2R3XGWEA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "SEE LICENSE IN LICENSE.txt",
+ "optionalDependencies": {
+ "@vscode/vsce-sign-alpine-arm64": "2.0.2",
+ "@vscode/vsce-sign-alpine-x64": "2.0.2",
+ "@vscode/vsce-sign-darwin-arm64": "2.0.2",
+ "@vscode/vsce-sign-darwin-x64": "2.0.2",
+ "@vscode/vsce-sign-linux-arm": "2.0.2",
+ "@vscode/vsce-sign-linux-arm64": "2.0.2",
+ "@vscode/vsce-sign-linux-x64": "2.0.2",
+ "@vscode/vsce-sign-win32-arm64": "2.0.2",
+ "@vscode/vsce-sign-win32-x64": "2.0.2"
+ }
+ },
+ "node_modules/@vscode/vsce-sign-alpine-arm64": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-alpine-arm64/-/vsce-sign-alpine-arm64-2.0.2.tgz",
+ "integrity": "sha512-E80YvqhtZCLUv3YAf9+tIbbqoinWLCO/B3j03yQPbjT3ZIHCliKZlsy1peNc4XNZ5uIb87Jn0HWx/ZbPXviuAQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "SEE LICENSE IN LICENSE.txt",
+ "optional": true,
+ "os": [
+ "alpine"
+ ]
+ },
+ "node_modules/@vscode/vsce-sign-alpine-x64": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-alpine-x64/-/vsce-sign-alpine-x64-2.0.2.tgz",
+ "integrity": "sha512-n1WC15MSMvTaeJ5KjWCzo0nzjydwxLyoHiMJHu1Ov0VWTZiddasmOQHekA47tFRycnt4FsQrlkSCTdgHppn6bw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "SEE LICENSE IN LICENSE.txt",
+ "optional": true,
+ "os": [
+ "alpine"
+ ]
+ },
+ "node_modules/@vscode/vsce-sign-darwin-arm64": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-darwin-arm64/-/vsce-sign-darwin-arm64-2.0.2.tgz",
+ "integrity": "sha512-rz8F4pMcxPj8fjKAJIfkUT8ycG9CjIp888VY/6pq6cuI2qEzQ0+b5p3xb74CJnBbSC0p2eRVoe+WgNCAxCLtzQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "SEE LICENSE IN LICENSE.txt",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@vscode/vsce-sign-darwin-x64": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-darwin-x64/-/vsce-sign-darwin-x64-2.0.2.tgz",
+ "integrity": "sha512-MCjPrQ5MY/QVoZ6n0D92jcRb7eYvxAujG/AH2yM6lI0BspvJQxp0o9s5oiAM9r32r9tkLpiy5s2icsbwefAQIw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "SEE LICENSE IN LICENSE.txt",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@vscode/vsce-sign-linux-arm": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-arm/-/vsce-sign-linux-arm-2.0.2.tgz",
+ "integrity": "sha512-Fkb5jpbfhZKVw3xwR6t7WYfwKZktVGNXdg1m08uEx1anO0oUPUkoQRsNm4QniL3hmfw0ijg00YA6TrxCRkPVOQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "SEE LICENSE IN LICENSE.txt",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@vscode/vsce-sign-linux-arm64": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-arm64/-/vsce-sign-linux-arm64-2.0.2.tgz",
+ "integrity": "sha512-Ybeu7cA6+/koxszsORXX0OJk9N0GgfHq70Wqi4vv2iJCZvBrOWwcIrxKjvFtwyDgdeQzgPheH5nhLVl5eQy7WA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "SEE LICENSE IN LICENSE.txt",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@vscode/vsce-sign-linux-x64": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-x64/-/vsce-sign-linux-x64-2.0.2.tgz",
+ "integrity": "sha512-NsPPFVtLaTlVJKOiTnO8Cl78LZNWy0Q8iAg+LlBiCDEgC12Gt4WXOSs2pmcIjDYzj2kY4NwdeN1mBTaujYZaPg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "SEE LICENSE IN LICENSE.txt",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@vscode/vsce-sign-win32-arm64": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-win32-arm64/-/vsce-sign-win32-arm64-2.0.2.tgz",
+ "integrity": "sha512-wPs848ymZ3Ny+Y1Qlyi7mcT6VSigG89FWQnp2qRYCyMhdJxOpA4lDwxzlpL8fG6xC8GjQjGDkwbkWUcCobvksQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "SEE LICENSE IN LICENSE.txt",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@vscode/vsce-sign-win32-x64": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-win32-x64/-/vsce-sign-win32-x64-2.0.2.tgz",
+ "integrity": "sha512-pAiRN6qSAhDM5SVOIxgx+2xnoVUePHbRNC7OD2aOR3WltTKxxF25OfpK8h8UQ7A0BuRkSgREbB59DBlFk4iAeg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "SEE LICENSE IN LICENSE.txt",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
"node_modules/@vscode/vsce/node_modules/ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
@@ -826,6 +1291,16 @@
"node": ">=4"
}
},
+ "node_modules/@vscode/vsce/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
"node_modules/@vscode/vsce/node_modules/chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -873,6 +1348,46 @@
"node": ">=0.8.0"
}
},
+ "node_modules/@vscode/vsce/node_modules/glob": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz",
+ "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^4.0.1",
+ "minimatch": "^10.0.0",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^2.0.0"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@vscode/vsce/node_modules/glob/node_modules/minimatch": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
+ "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/@vscode/vsce/node_modules/has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@@ -882,15 +1397,6 @@
"node": ">=4"
}
},
- "node_modules/@vscode/vsce/node_modules/semver": {
- "version": "5.7.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
- "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
- "dev": true,
- "bin": {
- "semver": "bin/semver"
- }
- },
"node_modules/@vscode/vsce/node_modules/supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@@ -903,19 +1409,6 @@
"node": ">=4"
}
},
- "node_modules/@vscode/vsce/node_modules/xml2js": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz",
- "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
- "dev": true,
- "dependencies": {
- "sax": ">=0.6.0",
- "xmlbuilder": "~11.0.0"
- },
- "engines": {
- "node": ">=4.0.0"
- }
- },
"node_modules/acorn": {
"version": "8.10.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
@@ -1007,11 +1500,19 @@
"node": ">=8"
}
},
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/azure-devops-node-api": {
- "version": "11.2.0",
- "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.2.0.tgz",
- "integrity": "sha512-XdiGPhrpaT5J8wdERRKs5g8E0Zy1pvOYTli7z9E8nmOn3YGp4FhtjhrOyFmX/8veWCwdI69mCHKJw6l+4J/bHA==",
+ "version": "12.5.0",
+ "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-12.5.0.tgz",
+ "integrity": "sha512-R5eFskGvOm3U/GzeAuxRkUsAl0hrAwGgWn6zAd2KrZmrEhWZVqLew4OOupbQlXUuojUzpGtq62SmdhJ06N88og==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"tunnel": "0.0.6",
"typed-rest-client": "^1.8.4"
@@ -1132,14 +1633,28 @@
"node": "*"
}
},
+ "node_modules/buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
"node_modules/call-bind": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
- "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
+ "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "function-bind": "^1.1.1",
- "get-intrinsic": "^1.0.2"
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -1234,6 +1749,16 @@
"node": ">=12"
}
},
+ "node_modules/cockatiel": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/cockatiel/-/cockatiel-3.2.1.tgz",
+ "integrity": "sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ }
+ },
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -1250,6 +1775,19 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/commander": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
@@ -1780,6 +2318,34 @@
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"dev": true
},
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/define-lazy-prop": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
+ "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/delaunator": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz",
@@ -1788,6 +2354,16 @@
"robust-predicates": "^3.0.0"
}
},
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/detect-libc": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
@@ -1877,6 +2453,23 @@
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -1904,6 +2497,29 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
+ "node_modules/es-define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
+ "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/esbuild": {
"version": "0.18.12",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.12.tgz",
@@ -2156,6 +2772,16 @@
"node": ">=0.10.0"
}
},
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
"node_modules/expand-template": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
@@ -2309,6 +2935,38 @@
}
}
},
+ "node_modules/foreground-child": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
+ "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
+ "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/fs-constants": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
@@ -2323,10 +2981,14 @@
"dev": true
},
"node_modules/function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
- "dev": true
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
},
"node_modules/get-caller-file": {
"version": "2.0.5",
@@ -2337,14 +2999,20 @@
}
},
"node_modules/get-intrinsic": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
- "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
+ "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.3"
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -2424,6 +3092,19 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "get-intrinsic": "^1.1.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/grapheme-splitter": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
@@ -2436,18 +3117,6 @@
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
"dev": true
},
- "node_modules/has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dev": true,
- "dependencies": {
- "function-bind": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4.0"
- }
- },
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -2457,11 +3126,38 @@
"node": ">=8"
}
},
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
+ "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
},
@@ -2469,6 +3165,19 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/hosted-git-info": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
@@ -2642,6 +3351,22 @@
"is-ci": "bin.js"
}
},
+ "node_modules/is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -2689,6 +3414,19 @@
"node": ">=8"
}
},
+ "node_modules/is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-docker": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@@ -2701,6 +3439,22 @@
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true
},
+ "node_modules/jackspeak": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz",
+ "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
@@ -2731,6 +3485,52 @@
"integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==",
"dev": true
},
+ "node_modules/jsonwebtoken": {
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
+ "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jws": "^3.2.2",
+ "lodash.includes": "^4.3.0",
+ "lodash.isboolean": "^3.0.3",
+ "lodash.isinteger": "^4.0.4",
+ "lodash.isnumber": "^3.0.3",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.isstring": "^4.0.1",
+ "lodash.once": "^4.0.0",
+ "ms": "^2.1.1",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=12",
+ "npm": ">=6"
+ }
+ },
+ "node_modules/jsonwebtoken/node_modules/jwa": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
+ "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "buffer-equal-constant-time": "1.0.1",
+ "ecdsa-sig-formatter": "1.0.11",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/jsonwebtoken/node_modules/jws": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
+ "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jwa": "^1.4.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
"node_modules/jszip": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
@@ -2743,6 +3543,29 @@
"setimmediate": "^1.0.5"
}
},
+ "node_modules/jwa": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz",
+ "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "buffer-equal-constant-time": "1.0.1",
+ "ecdsa-sig-formatter": "1.0.11",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/jws": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
+ "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jwa": "^2.0.0",
+ "safe-buffer": "^5.0.1"
+ }
+ },
"node_modules/keytar": {
"version": "7.9.0",
"resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz",
@@ -2787,12 +3610,13 @@
}
},
"node_modules/linkify-it": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz",
- "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
+ "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "uc.micro": "^1.0.1"
+ "uc.micro": "^2.0.0"
}
},
"node_modules/locate-path": {
@@ -2810,12 +3634,61 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/lodash.includes": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
+ "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lodash.isboolean": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+ "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lodash.isinteger": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
+ "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lodash.isnumber": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
+ "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true
},
+ "node_modules/lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
@@ -2828,35 +3701,29 @@
}
},
"node_modules/markdown-it": {
- "version": "12.3.2",
- "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz",
- "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==",
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
+ "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"argparse": "^2.0.1",
- "entities": "~2.1.0",
- "linkify-it": "^3.0.1",
- "mdurl": "^1.0.1",
- "uc.micro": "^1.0.5"
+ "entities": "^4.4.0",
+ "linkify-it": "^5.0.0",
+ "mdurl": "^2.0.0",
+ "punycode.js": "^2.3.1",
+ "uc.micro": "^2.1.0"
},
"bin": {
- "markdown-it": "bin/markdown-it.js"
- }
- },
- "node_modules/markdown-it/node_modules/entities": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
- "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==",
- "dev": true,
- "funding": {
- "url": "https://github.com/fb55/entities?sponsor=1"
+ "markdown-it": "bin/markdown-it.mjs"
}
},
"node_modules/mdurl": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
- "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==",
- "dev": true
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
+ "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/merge2": {
"version": "1.4.1",
@@ -2868,12 +3735,13 @@
}
},
"node_modules/micromatch": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
- "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "braces": "^3.0.2",
+ "braces": "^3.0.3",
"picomatch": "^2.3.1"
},
"engines": {
@@ -2892,6 +3760,29 @@
"node": ">=4"
}
},
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/mimic-response": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
@@ -2927,6 +3818,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
"node_modules/mkdirp-classic": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
@@ -2998,10 +3899,14 @@
}
},
"node_modules/object-inspect": {
- "version": "1.12.3",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
- "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz",
+ "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==",
"dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -3015,6 +3920,24 @@
"wrappy": "1"
}
},
+ "node_modules/open": {
+ "version": "8.4.2",
+ "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz",
+ "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-lazy-prop": "^2.0.0",
+ "is-docker": "^2.1.1",
+ "is-wsl": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/optionator": {
"version": "0.9.3",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
@@ -3053,6 +3976,93 @@
"node": ">= 14"
}
},
+ "node_modules/ovsx/node_modules/@vscode/vsce": {
+ "version": "2.32.0",
+ "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.32.0.tgz",
+ "integrity": "sha512-3EFJfsgrSftIqt3EtdRcAygy/OJ3hstyI1cDmIgkU9CFZW5C+3djr6mfosndCUqcVYuyjmxOK1xmFp/Bq7+NIg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@azure/identity": "^4.1.0",
+ "@vscode/vsce-sign": "^2.0.0",
+ "azure-devops-node-api": "^12.5.0",
+ "chalk": "^2.4.2",
+ "cheerio": "^1.0.0-rc.9",
+ "cockatiel": "^3.1.2",
+ "commander": "^6.2.1",
+ "form-data": "^4.0.0",
+ "glob": "^7.0.6",
+ "hosted-git-info": "^4.0.2",
+ "jsonc-parser": "^3.2.0",
+ "leven": "^3.1.0",
+ "markdown-it": "^12.3.2",
+ "mime": "^1.3.4",
+ "minimatch": "^3.0.3",
+ "parse-semver": "^1.1.1",
+ "read": "^1.0.7",
+ "semver": "^7.5.2",
+ "tmp": "^0.2.1",
+ "typed-rest-client": "^1.8.4",
+ "url-join": "^4.0.1",
+ "xml2js": "^0.5.0",
+ "yauzl": "^2.3.1",
+ "yazl": "^2.2.2"
+ },
+ "bin": {
+ "vsce": "vsce"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "optionalDependencies": {
+ "keytar": "^7.7.0"
+ }
+ },
+ "node_modules/ovsx/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ovsx/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ovsx/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/ovsx/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/ovsx/node_modules/commander": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
@@ -3062,6 +4072,90 @@
"node": ">= 6"
}
},
+ "node_modules/ovsx/node_modules/entities": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
+ "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/ovsx/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/ovsx/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ovsx/node_modules/linkify-it": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz",
+ "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "uc.micro": "^1.0.1"
+ }
+ },
+ "node_modules/ovsx/node_modules/markdown-it": {
+ "version": "12.3.2",
+ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz",
+ "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1",
+ "entities": "~2.1.0",
+ "linkify-it": "^3.0.1",
+ "mdurl": "^1.0.1",
+ "uc.micro": "^1.0.5"
+ },
+ "bin": {
+ "markdown-it": "bin/markdown-it.js"
+ }
+ },
+ "node_modules/ovsx/node_modules/mdurl": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
+ "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/ovsx/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ovsx/node_modules/uc.micro": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
+ "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
@@ -3092,6 +4186,13 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0"
+ },
"node_modules/pako": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
@@ -3180,6 +4281,33 @@
"node": ">=8"
}
},
+ "node_modules/path-scurry": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz",
+ "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^11.0.0",
+ "minipass": "^7.1.2"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-scurry/node_modules/lru-cache": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.1.tgz",
+ "integrity": "sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
"node_modules/path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
@@ -3284,13 +4412,24 @@
"node": ">=6"
}
},
+ "node_modules/punycode.js": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
+ "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/qs": {
- "version": "6.11.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
- "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
+ "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
- "side-channel": "^1.0.4"
+ "side-channel": "^1.0.6"
},
"engines": {
"node": ">=0.6"
@@ -3478,6 +4617,24 @@
"node": ">=10"
}
},
+ "node_modules/set-function-length": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/setimmediate": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
@@ -3506,19 +4663,37 @@
}
},
"node_modules/side-channel": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
- "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
+ "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.0",
- "get-intrinsic": "^1.0.2",
- "object-inspect": "^1.9.0"
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4",
+ "object-inspect": "^1.13.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/simple-concat": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
@@ -3575,6 +4750,17 @@
"node": ">=8"
}
},
+ "node_modules/stoppable": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz",
+ "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4",
+ "npm": ">=6"
+ }
+ },
"node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -3597,6 +4783,22 @@
"node": ">=8"
}
},
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
@@ -3608,6 +4810,20 @@
"node": ">=8"
}
},
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
@@ -3684,15 +4900,13 @@
"dev": true
},
"node_modules/tmp": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
- "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
+ "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==",
"dev": true,
- "dependencies": {
- "rimraf": "^3.0.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=8.17.0"
+ "node": ">=14.14"
}
},
"node_modules/to-regex-range": {
@@ -3720,16 +4934,18 @@
}
},
"node_modules/tslib": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
- "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==",
- "dev": true
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz",
+ "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==",
+ "dev": true,
+ "license": "0BSD"
},
"node_modules/tunnel": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
}
@@ -3772,10 +4988,11 @@
}
},
"node_modules/typed-rest-client": {
- "version": "1.8.9",
- "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.9.tgz",
- "integrity": "sha512-uSmjE38B80wjL85UFX3sTYEUlvZ1JgCRhsWj/fJ4rZ0FqDUFoIuodtiVeE+cUqiVTOKPdKrp/sdftD15MDek6g==",
+ "version": "1.8.11",
+ "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.11.tgz",
+ "integrity": "sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"qs": "^6.9.1",
"tunnel": "0.0.6",
@@ -3783,10 +5000,11 @@
}
},
"node_modules/typescript": {
- "version": "5.1.6",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
- "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==",
+ "version": "5.6.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
+ "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
"dev": true,
+ "license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -3796,16 +5014,18 @@
}
},
"node_modules/uc.micro": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
- "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
- "dev": true
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
+ "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/underscore": {
- "version": "1.13.6",
- "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz",
- "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==",
- "dev": true
+ "version": "1.13.7",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz",
+ "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/uri-js": {
"version": "4.4.1",
@@ -3828,6 +5048,16 @@
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"dev": true
},
+ "node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
"node_modules/vscode-jsonrpc": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.1.0.tgz",
@@ -3913,12 +5143,45 @@
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"dev": true
},
+ "node_modules/xml2js": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz",
+ "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "sax": ">=0.6.0",
+ "xmlbuilder": "~11.0.0"
+ },
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
"node_modules/xmlbuilder": {
"version": "11.0.1",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
diff --git a/editors/code/package.json b/editors/code/package.json
index a52b3d1ec5..e55eceff78 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -58,14 +58,14 @@
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"@vscode/test-electron": "^2.3.8",
- "@vscode/vsce": "^2.19.0",
+ "@vscode/vsce": "^3.0.0",
"esbuild": "^0.18.12",
"eslint": "^8.44.0",
"eslint-config-prettier": "^8.8.0",
"ovsx": "^0.8.2",
"prettier": "^3.0.0",
"tslib": "^2.6.0",
- "typescript": "^5.1.6"
+ "typescript": "^5.6.0"
},
"activationEvents": [
"workspaceContains:Cargo.toml",
@@ -349,6 +349,11 @@
"markdownDescription": "Whether to show the test explorer.",
"default": false,
"type": "boolean"
+ },
+ "rust-analyzer.initializeStopped": {
+ "markdownDescription": "Do not start rust-analyzer server when the extension is activated.",
+ "default": false,
+ "type": "boolean"
}
}
},
@@ -728,8 +733,8 @@
"rust-analyzer.cargo.cfgs": {
"markdownDescription": "List of cfg options to enable with the given values.",
"default": {
- "debug_assertions": null,
- "miri": null
+ "miri": null,
+ "debug_assertions": null
},
"type": "object"
}
@@ -1152,18 +1157,10 @@
"rust-analyzer.completion.snippets.custom": {
"markdownDescription": "Custom completion snippets.",
"default": {
- "Arc::new": {
- "postfix": "arc",
- "body": "Arc::new(${receiver})",
- "requires": "std::sync::Arc",
- "description": "Put the expression into an `Arc`",
- "scope": "expr"
- },
- "Rc::new": {
- "postfix": "rc",
- "body": "Rc::new(${receiver})",
- "requires": "std::rc::Rc",
- "description": "Put the expression into an `Rc`",
+ "Ok": {
+ "postfix": "ok",
+ "body": "Ok(${receiver})",
+ "description": "Wrap the expression in a `Result::Ok`",
"scope": "expr"
},
"Box::pin": {
@@ -1173,10 +1170,11 @@
"description": "Put the expression into a pinned `Box`",
"scope": "expr"
},
- "Err": {
- "postfix": "err",
- "body": "Err(${receiver})",
- "description": "Wrap the expression in a `Result::Err`",
+ "Arc::new": {
+ "postfix": "arc",
+ "body": "Arc::new(${receiver})",
+ "requires": "std::sync::Arc",
+ "description": "Put the expression into an `Arc`",
"scope": "expr"
},
"Some": {
@@ -1185,10 +1183,17 @@
"description": "Wrap the expression in an `Option::Some`",
"scope": "expr"
},
- "Ok": {
- "postfix": "ok",
- "body": "Ok(${receiver})",
- "description": "Wrap the expression in a `Result::Ok`",
+ "Err": {
+ "postfix": "err",
+ "body": "Err(${receiver})",
+ "description": "Wrap the expression in a `Result::Err`",
+ "scope": "expr"
+ },
+ "Rc::new": {
+ "postfix": "rc",
+ "body": "Rc::new(${receiver})",
+ "requires": "std::rc::Rc",
+ "description": "Put the expression into an `Rc`",
"scope": "expr"
}
},
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts
index abb4099f9f..67bc72f1e1 100644
--- a/editors/code/src/config.ts
+++ b/editors/code/src/config.ts
@@ -330,6 +330,10 @@ export class Config {
get statusBarClickAction() {
return this.get<string>("statusBar.clickAction");
}
+
+ get initializeStopped() {
+ return this.get<boolean>("initializeStopped");
+ }
}
export function prepareVSCodeConfig<T>(resp: T): T {
diff --git a/editors/code/src/debug.ts b/editors/code/src/debug.ts
index 77ab44f24c..9e2e3d2185 100644
--- a/editors/code/src/debug.ts
+++ b/editors/code/src/debug.ts
@@ -6,7 +6,6 @@ import type * as ra from "./lsp_ext";
import { Cargo } from "./toolchain";
import type { Ctx } from "./ctx";
import { createTaskFromRunnable, prepareEnv } from "./run";
-import { execSync } from "node:child_process";
import { execute, isCargoRunnableArgs, unwrapUndefinable } from "./util";
import type { Config } from "./config";
@@ -152,9 +151,24 @@ async function getDebugConfiguration(
const env = prepareEnv(inheritEnv, runnable.label, runnableArgs, config.runnablesExtraEnv);
const executable = await getDebugExecutable(runnableArgs, env);
let sourceFileMap = debugOptions.sourceFileMap;
+
if (sourceFileMap === "auto") {
sourceFileMap = {};
- await discoverSourceFileMap(sourceFileMap, env, wsFolder);
+ const computedSourceFileMap = await discoverSourceFileMap(env, wsFolder);
+
+ if (computedSourceFileMap) {
+ // lldb-dap requires passing the source map as an array of two element arrays.
+ // the two element array contains a source and destination pathname.
+ // TODO: remove lldb-dap-specific post-processing once
+ // https://github.com/llvm/llvm-project/pull/106919/ is released in the extension.
+ if (provider.type === "lldb-dap") {
+ provider.additional["sourceMap"] = [
+ [computedSourceFileMap?.source, computedSourceFileMap?.destination],
+ ];
+ } else {
+ sourceFileMap[computedSourceFileMap.source] = computedSourceFileMap.destination;
+ }
+ }
}
const debugConfig = getDebugConfig(
@@ -189,11 +203,15 @@ async function getDebugConfiguration(
return debugConfig;
}
+type SourceFileMap = {
+ source: string;
+ destination: string;
+};
+
async function discoverSourceFileMap(
- sourceFileMap: Record<string, string>,
env: Record<string, string>,
cwd: string,
-) {
+): Promise<SourceFileMap | undefined> {
const sysroot = env["RUSTC_TOOLCHAIN"];
if (sysroot) {
// let's try to use the default toolchain
@@ -203,9 +221,11 @@ async function discoverSourceFileMap(
const commitHash = rx.exec(data)?.[1];
if (commitHash) {
const rustlib = path.normalize(sysroot + "/lib/rustlib/src/rust");
- sourceFileMap[`/rustc/${commitHash}/`] = rustlib;
+ return { source: rustlib, destination: rustlib };
}
}
+
+ return;
}
type PropertyFetcher<Config, Input, Key extends keyof Config> = (
@@ -218,7 +238,7 @@ type DebugConfigProvider<Type extends string, DebugConfig extends BaseDebugConfi
runnableArgsProperty: PropertyFetcher<DebugConfig, ra.CargoRunnableArgs, keyof DebugConfig>;
sourceFileMapProperty?: keyof DebugConfig;
type: Type;
- additional?: Record<string, unknown>;
+ additional: Record<string, unknown>;
};
type KnownEnginesType = (typeof knownEngines)[keyof typeof knownEngines];
@@ -236,16 +256,7 @@ const knownEngines: {
"args",
runnableArgs.executableArgs,
],
- additional: {
- sourceMap: [
- [
- `/rustc/${/commit-hash:\s(.*)$/m.exec(
- execSync("rustc -V -v", {}).toString(),
- )?.[1]}/library`,
- "${config:rust-analyzer.cargo.sysroot}/lib/rustlib/src/rust/library",
- ],
- ],
- },
+ additional: {},
},
"vadimcn.vscode-lldb": {
type: "lldb",
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index 0ddc5619e9..fdf43f66f9 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -107,7 +107,14 @@ async function activateServer(ctx: Ctx): Promise<RustAnalyzerExtensionApi> {
initializeDebugSessionTrackingAndRebuild(ctx);
}
- await ctx.start();
+ if (ctx.config.initializeStopped) {
+ ctx.setServerStatus({
+ health: "stopped",
+ });
+ } else {
+ await ctx.start();
+ }
+
return ctx;
}
diff --git a/lib/line-index/Cargo.toml b/lib/line-index/Cargo.toml
index 8ae4954dd0..14196ba3d0 100644
--- a/lib/line-index/Cargo.toml
+++ b/lib/line-index/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "line-index"
-version = "0.1.1"
+version = "0.1.2"
description = "Maps flat `TextSize` offsets to/from `(line, column)` representation."
license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-lang/rust-analyzer/tree/master/lib/line-index"
diff --git a/lib/line-index/src/lib.rs b/lib/line-index/src/lib.rs
index 66875e2524..6f0455ee98 100644
--- a/lib/line-index/src/lib.rs
+++ b/lib/line-index/src/lib.rs
@@ -177,6 +177,14 @@ impl LineIndex {
Some(LineCol { line: line_col.line, col })
}
+ /// Returns the given line's range.
+ pub fn line(&self, line: u32) -> Option<TextRange> {
+ let start = self.start_offset(line as usize)?;
+ let next_newline = self.newlines.get(line as usize).copied().unwrap_or(self.len);
+ let line_length = next_newline - start;
+ Some(TextRange::new(start, start + line_length))
+ }
+
/// Given a range [start, end), returns a sorted iterator of non-empty ranges [start, x1), [x1,
/// x2), ..., [xn, end) where all the xi, which are positions of newlines, are inside the range
/// [start, end).
diff --git a/lib/line-index/src/tests.rs b/lib/line-index/src/tests.rs
index 57fad1dfc0..f2bb04aec3 100644
--- a/lib/line-index/src/tests.rs
+++ b/lib/line-index/src/tests.rs
@@ -195,3 +195,26 @@ fn test_every_chars() {
}
}
}
+
+#[test]
+fn test_line() {
+ use text_size::TextRange;
+
+ macro_rules! validate {
+ ($text:expr, $line:expr, $expected_start:literal .. $expected_end:literal) => {
+ let line_index = LineIndex::new($text);
+ assert_eq!(
+ line_index.line($line),
+ Some(TextRange::new(
+ TextSize::from($expected_start),
+ TextSize::from($expected_end)
+ ))
+ );
+ };
+ }
+
+ validate!("", 0, 0..0);
+ validate!("\n", 1, 1..1);
+ validate!("\nabc", 1, 1..4);
+ validate!("\nabc\ndef", 1, 1..5);
+}
diff --git a/rust-version b/rust-version
index d0f9fa7ac4..bc324402a9 100644
--- a/rust-version
+++ b/rust-version
@@ -1 +1 @@
-dd5127615ad626741a1116d022cf784637ac05df
+1de57a5ce952c722f7053aeacfc6c90bc139b678
diff --git a/xtask/src/codegen/grammar/ast_src.rs b/xtask/src/codegen/grammar/ast_src.rs
index f1a96e0c6a..9269d15423 100644
--- a/xtask/src/codegen/grammar/ast_src.rs
+++ b/xtask/src/codegen/grammar/ast_src.rs
@@ -111,7 +111,7 @@ const RESERVED: &[&str] = &[
// keywords that are keywords only in specific parse contexts
#[doc(alias = "WEAK_KEYWORDS")]
const CONTEXTUAL_KEYWORDS: &[&str] =
- &["macro_rules", "union", "default", "raw", "dyn", "auto", "yeet"];
+ &["macro_rules", "union", "default", "raw", "dyn", "auto", "yeet", "safe"];
// keywords we use for special macro expansions
const CONTEXTUAL_BUILTIN_KEYWORDS: &[&str] = &[
"asm",