From dba167592ee67748d2f24c8f646cbe193c95da14 Mon Sep 17 00:00:00 2001 From: Young-Flash <871946895@qq.com> Date: Thu, 16 Nov 2023 17:22:53 +0800 Subject: [PATCH 01/69] feat: add hover display for trait assoc items --- crates/hir/src/display.rs | 24 ++++++++ crates/ide/src/hover/tests.rs | 113 +++++++++++++++++++++++++++++++--- 2 files changed, 127 insertions(+), 10 deletions(-) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 30f402a79f3d..d76eb873bf4e 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -595,6 +595,30 @@ impl HirDisplay for Trait { let def_id = GenericDefId::TraitId(self.id); write_generic_params(def_id, f)?; write_where_clause(def_id, f)?; + + let assoc_items = self.items(f.db); + if assoc_items.is_empty() { + f.write_str(" {}")?; + } else { + f.write_str(" {\n")?; + for item in assoc_items { + f.write_str(" ")?; + match item { + AssocItem::Function(func) => { + func.hir_fmt(f)?; + } + AssocItem::Const(cst) => { + cst.hir_fmt(f)?; + } + AssocItem::TypeAlias(type_alias) => { + type_alias.hir_fmt(f)?; + } + }; + f.write_str(",\n")?; + } + f.write_str("}")?; + } + Ok(()) } } diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index ead4f91595f0..73d9339a229e 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -2685,7 +2685,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, ], @@ -2719,7 +2719,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, HoverGotoTypeData { @@ -2886,7 +2886,7 @@ fn foo(ar$0g: &impl Foo) {} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, ], @@ -2988,7 +2988,7 @@ pub mod future { name: "Future", kind: Trait, container_name: "future", - description: "pub trait Future", + description: "pub trait Future {}", }, }, HoverGotoTypeData { @@ -3033,7 +3033,7 @@ fn foo(ar$0g: &impl Foo) {} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, HoverGotoTypeData { @@ -3096,7 +3096,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, ], @@ -3127,7 +3127,7 @@ fn foo(ar$0g: &dyn Foo) {} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, ], @@ -3159,7 +3159,7 @@ fn foo(ar$0g: &dyn Foo) {} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, HoverGotoTypeData { @@ -3288,7 +3288,7 @@ fn main() { let s$0t = test().get(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {\n type Item,\n fn get(self) -> Self::Item,\n}", }, }, ], @@ -3353,7 +3353,7 @@ fn foo(t: T$0){} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, ], @@ -6252,6 +6252,99 @@ impl T for () { ); } +#[test] +fn hover_trait_show_assoc_items() { + check( + r#" +trait T {} +impl T$0 for () {} +"#, + expect![[r#" + *T* + + ```rust + test + ``` + + ```rust + trait T {} + ``` + "#]], + ); + + check( + r#" +trait T { + fn func() {} +} +impl T$0 for () {} +"#, + expect![[r#" + *T* + + ```rust + test + ``` + + ```rust + trait T { + fn func(), + } + ``` + "#]], + ); + + check( + r#" +trait T { + fn func() {} + const FLAG: i32 = 34; +} +impl T$0 for () {} +"#, + expect![[r#" + *T* + + ```rust + test + ``` + + ```rust + trait T { + fn func(), + const FLAG: i32, + } + ``` + "#]], + ); + + check( + r#" +trait T { + fn func() {} + const FLAG: i32 = 34; + type Bar; +} +impl T$0 for () {} +"#, + expect![[r#" + *T* + + ```rust + test + ``` + + ```rust + trait T { + fn func(), + const FLAG: i32, + type Bar, + } + ``` + "#]], + ); +} + #[test] fn hover_ranged_macro_call() { check_hover_range( From 00358b1fe078bc4d702375203f79b088d2b9a5f6 Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Sun, 18 Feb 2024 15:29:45 +0800 Subject: [PATCH 02/69] rebase on lastest master --- crates/hir/src/display.rs | 5 +---- crates/ide/src/hover/tests.rs | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index d76eb873bf4e..010c3537574c 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -17,10 +17,7 @@ use hir_ty::{ }; use crate::{ - Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, Field, - Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, SelfParam, - Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias, TypeOrConstParam, - TypeParam, Union, Variant, + Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, Field, Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, SelfParam, Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam, Union, Variant }; impl HirDisplay for Function { diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 73d9339a229e..e845ef668948 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -411,7 +411,7 @@ fn main() { name: "FnOnce", kind: Trait, container_name: "function", - description: "pub trait FnOnce\nwhere\n Args: Tuple,", + description: "pub trait FnOnce\nwhere\n Args: Tuple, {\n pub type Output,\n pub extern \"rust-call\" fn call_once(self, args: Args) -> Self::Output,\n}", }, }, ], @@ -2766,7 +2766,7 @@ fn main() { let s$0t = foo(); } focus_range: 19..22, name: "Bar", kind: Trait, - description: "trait Bar", + description: "trait Bar {}", }, }, HoverGotoTypeData { @@ -2779,7 +2779,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, ], @@ -2816,7 +2816,7 @@ fn main() { let s$0t = foo(); } focus_range: 22..25, name: "Bar", kind: Trait, - description: "trait Bar", + description: "trait Bar {}", }, }, HoverGotoTypeData { @@ -2829,7 +2829,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, HoverGotoTypeData { @@ -2920,7 +2920,7 @@ fn foo(ar$0g: &impl Foo + Bar) {} focus_range: 19..22, name: "Bar", kind: Trait, - description: "trait Bar", + description: "trait Bar {}", }, }, HoverGotoTypeData { @@ -2933,7 +2933,7 @@ fn foo(ar$0g: &impl Foo + Bar) {} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, HoverGotoTypeData { @@ -3220,7 +3220,7 @@ fn foo(a$0rg: &impl ImplTrait>>>) {} focus_range: 28..36, name: "DynTrait", kind: Trait, - description: "trait DynTrait", + description: "trait DynTrait {}", }, }, HoverGotoTypeData { @@ -3233,7 +3233,7 @@ fn foo(a$0rg: &impl ImplTrait>>>) {} focus_range: 6..15, name: "ImplTrait", kind: Trait, - description: "trait ImplTrait", + description: "trait ImplTrait {}", }, }, HoverGotoTypeData { @@ -7456,7 +7456,7 @@ impl Iterator for S { name: "Future", kind: Trait, container_name: "future", - description: "pub trait Future", + description: "pub trait Future {\n pub type Output,\n pub fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll,\n}", }, }, HoverGotoTypeData { @@ -7470,7 +7470,7 @@ impl Iterator for S { name: "Iterator", kind: Trait, container_name: "iterator", - description: "pub trait Iterator", + description: "pub trait Iterator {\n pub type Item,\n pub fn next(&mut self) -> Option,\n pub fn nth(&mut self, n: usize) -> Option,\n pub fn by_ref(&mut self) -> &mut Self\nwhere\n Self: Sized,,\n}", }, }, HoverGotoTypeData { @@ -7483,7 +7483,7 @@ impl Iterator for S { focus_range: 49..56, name: "Notable", kind: Trait, - description: "trait Notable", + description: "trait Notable {}", }, }, HoverGotoTypeData { From 35ec5955eb607c17d72621fab8cf59242d6bac84 Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Sun, 18 Feb 2024 17:43:22 +0800 Subject: [PATCH 03/69] add config item for hover display --- crates/hir-ty/src/display.rs | 2 +- crates/hir/src/display.rs | 9 ++++++++- crates/ide-db/src/defs.rs | 4 ++-- crates/ide/src/hover.rs | 1 + crates/ide/src/hover/render.rs | 2 +- crates/ide/src/hover/tests.rs | 1 + crates/ide/src/static_index.rs | 3 ++- crates/rust-analyzer/src/config.rs | 5 ++++- docs/user/generated_config.adoc | 5 +++++ editors/code/package.json | 9 +++++++++ 10 files changed, 34 insertions(+), 7 deletions(-) diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index fe51ec3f8210..f7e396de2d6b 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -62,7 +62,7 @@ pub struct HirFormatter<'a> { fmt: &'a mut dyn HirWrite, buf: String, curr_size: usize, - pub(crate) max_size: Option, + pub max_size: Option, omit_verbose_types: bool, closure_style: ClosureStyle, display_target: DisplayTarget, diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 010c3537574c..0e221a2149ae 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -593,12 +593,14 @@ impl HirDisplay for Trait { write_generic_params(def_id, f)?; write_where_clause(def_id, f)?; + let mut display_size = 0; + let max_display_size = f.max_size.unwrap_or(7); let assoc_items = self.items(f.db); if assoc_items.is_empty() { f.write_str(" {}")?; } else { f.write_str(" {\n")?; - for item in assoc_items { + for (index, item) in assoc_items.iter().enumerate() { f.write_str(" ")?; match item { AssocItem::Function(func) => { @@ -612,6 +614,11 @@ impl HirDisplay for Trait { } }; f.write_str(",\n")?; + display_size += 1; + if display_size == max_display_size && index != assoc_items.len() - 1{ + f.write_str(" ...\n")?; + break; + } } f.write_str("}")?; } diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs index 1b6ff8bad53c..8de885f49948 100644 --- a/crates/ide-db/src/defs.rs +++ b/crates/ide-db/src/defs.rs @@ -213,7 +213,7 @@ impl Definition { }) } - pub fn label(&self, db: &RootDatabase) -> String { + pub fn label(&self, db: &RootDatabase, max_size: Option) -> String { match *self { Definition::Macro(it) => it.display(db).to_string(), Definition::Field(it) => it.display(db).to_string(), @@ -224,7 +224,7 @@ impl Definition { Definition::Variant(it) => it.display(db).to_string(), Definition::Const(it) => it.display(db).to_string(), Definition::Static(it) => it.display(db).to_string(), - Definition::Trait(it) => it.display(db).to_string(), + Definition::Trait(it) => it.display_truncated(db, max_size).to_string(), Definition::TraitAlias(it) => it.display(db).to_string(), Definition::TypeAlias(it) => it.display(db).to_string(), Definition::BuiltinType(it) => it.name().display(db).to_string(), diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 4a7350feb385..4b3fdaff0b34 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -32,6 +32,7 @@ pub struct HoverConfig { pub documentation: bool, pub keywords: bool, pub format: HoverDocFormat, + pub trait_item_display_on_hover: Option, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index 563e78253a8a..c955f46bc454 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -406,7 +406,7 @@ pub(super) fn definition( config: &HoverConfig, ) -> Markup { let mod_path = definition_mod_path(db, &def); - let label = def.label(db); + let label = def.label(db, config.trait_item_display_on_hover); let docs = def.docs(db, famous_defs); let value = (|| match def { Definition::Variant(it) => { diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index e845ef668948..2df4ca5810b2 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -17,6 +17,7 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig { documentation: true, format: HoverDocFormat::Markdown, keywords: true, + trait_item_display_on_hover: Some(7), }; fn check_hover_no_result(ra_fixture: &str) { diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index 2929a7522e59..8d5f5e1bf677 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -166,6 +166,7 @@ impl StaticIndex<'_> { documentation: true, keywords: true, format: crate::HoverDocFormat::Markdown, + trait_item_display_on_hover: Some(7) }; let tokens = tokens.filter(|token| { matches!( @@ -196,7 +197,7 @@ impl StaticIndex<'_> { enclosing_moniker: current_crate .zip(def.enclosing_definition(self.db)) .and_then(|(cc, enclosing_def)| def_to_moniker(self.db, enclosing_def, cc)), - signature: Some(def.label(self.db)), + signature: Some(def.label(self.db, hover_config.trait_item_display_on_hover)), kind: def_to_kind(self.db, def), }); self.def_map.insert(def, it); diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 16e1a2f54490..230a0385cdb3 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -511,7 +511,6 @@ config_data! { /// Exclude tests from find-all-references. references_excludeTests: bool = "false", - /// Command to be executed instead of 'cargo' for runnables. runnables_command: Option = "null", /// Additional arguments to be passed to cargo for runnables such as @@ -591,6 +590,9 @@ config_data! { /// Show documentation. signatureInfo_documentation_enable: bool = "true", + /// How many trait item display on hover. + trait_item_display_on_hover: Option = "7", + /// Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list. typing_autoClosingAngleBrackets_enable: bool = "false", @@ -1683,6 +1685,7 @@ impl Config { } }, keywords: self.data.hover_documentation_keywords_enable, + trait_item_display_on_hover: self.data.trait_item_display_on_hover, } } diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index da7654b0f644..9f3ab4513294 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -927,6 +927,11 @@ Show full signature of the callable. Only shows parameters if disabled. -- Show documentation. -- +[[rust-analyzer.trait.item.display.on.hover]]rust-analyzer.trait.item.display.on.hover (default: `7`):: ++ +-- +How many trait item display on hover. +-- [[rust-analyzer.typing.autoClosingAngleBrackets.enable]]rust-analyzer.typing.autoClosingAngleBrackets.enable (default: `false`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index 3a1df5a2f901..a4f54ae4f458 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -1648,6 +1648,15 @@ "default": true, "type": "boolean" }, + "rust-analyzer.trait.item.display.on.hover": { + "markdownDescription": "How many trait item display on hover.", + "default": 7, + "type": [ + "null", + "integer" + ], + "minimum": 0 + }, "rust-analyzer.typing.autoClosingAngleBrackets.enable": { "markdownDescription": "Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list.", "default": false, From 2e87f31fe9f9a147d7a19202e5c4f918b8c975ac Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Thu, 22 Feb 2024 17:37:40 +0800 Subject: [PATCH 04/69] add HoverDisplayConfig --- crates/hir/src/display.rs | 12 +++++++----- crates/ide-db/src/defs.rs | 12 ++++++++++-- crates/ide/src/hover.rs | 2 +- crates/ide/src/hover/render.rs | 5 +++-- crates/ide/src/hover/tests.rs | 2 +- crates/ide/src/static_index.rs | 6 +++--- crates/rust-analyzer/src/config.rs | 4 ++-- docs/user/generated_config.adoc | 2 +- editors/code/package.json | 2 +- 9 files changed, 29 insertions(+), 18 deletions(-) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 0e221a2149ae..08e0c6e75247 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -17,7 +17,10 @@ use hir_ty::{ }; use crate::{ - Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, Field, Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, SelfParam, Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam, Union, Variant + Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, + Field, Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, + SelfParam, Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias, + TypeOrConstParam, TypeParam, Union, Variant, }; impl HirDisplay for Function { @@ -593,9 +596,9 @@ impl HirDisplay for Trait { write_generic_params(def_id, f)?; write_where_clause(def_id, f)?; - let mut display_size = 0; - let max_display_size = f.max_size.unwrap_or(7); let assoc_items = self.items(f.db); + let assoc_items_size = assoc_items.len(); + let max_display_size = f.max_size.unwrap_or(assoc_items_size); if assoc_items.is_empty() { f.write_str(" {}")?; } else { @@ -614,8 +617,7 @@ impl HirDisplay for Trait { } }; f.write_str(",\n")?; - display_size += 1; - if display_size == max_display_size && index != assoc_items.len() - 1{ + if index + 1 == max_display_size && index + 1 != assoc_items_size { f.write_str(" ...\n")?; break; } diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs index 8de885f49948..35aaf864696a 100644 --- a/crates/ide-db/src/defs.rs +++ b/crates/ide-db/src/defs.rs @@ -24,6 +24,12 @@ use crate::documentation::{Documentation, HasDocs}; use crate::famous_defs::FamousDefs; use crate::RootDatabase; +#[derive(Default)] +pub struct HoverDisplayConfig { + pub trait_item_display_num: Option, + // todo: add config for struct & enum +} + // FIXME: a more precise name would probably be `Symbol`? #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] pub enum Definition { @@ -213,7 +219,7 @@ impl Definition { }) } - pub fn label(&self, db: &RootDatabase, max_size: Option) -> String { + pub fn label(&self, db: &RootDatabase, hover_display_config: HoverDisplayConfig) -> String { match *self { Definition::Macro(it) => it.display(db).to_string(), Definition::Field(it) => it.display(db).to_string(), @@ -224,7 +230,9 @@ impl Definition { Definition::Variant(it) => it.display(db).to_string(), Definition::Const(it) => it.display(db).to_string(), Definition::Static(it) => it.display(db).to_string(), - Definition::Trait(it) => it.display_truncated(db, max_size).to_string(), + Definition::Trait(it) => { + it.display_truncated(db, hover_display_config.trait_item_display_num).to_string() + } Definition::TraitAlias(it) => it.display(db).to_string(), Definition::TypeAlias(it) => it.display(db).to_string(), Definition::BuiltinType(it) => it.name().display(db).to_string(), diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 4b3fdaff0b34..64346a59b77f 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -32,7 +32,7 @@ pub struct HoverConfig { pub documentation: bool, pub keywords: bool, pub format: HoverDocFormat, - pub trait_item_display_on_hover: Option, + pub trait_item_display_num: Option, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index c955f46bc454..6d7886feec33 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -8,7 +8,7 @@ use hir::{ }; use ide_db::{ base_db::SourceDatabase, - defs::Definition, + defs::{Definition, HoverDisplayConfig}, documentation::HasDocs, famous_defs::FamousDefs, generated::lints::{CLIPPY_LINTS, DEFAULT_LINTS, FEATURES}, @@ -406,7 +406,8 @@ pub(super) fn definition( config: &HoverConfig, ) -> Markup { let mod_path = definition_mod_path(db, &def); - let label = def.label(db, config.trait_item_display_on_hover); + let hover_config = HoverDisplayConfig { trait_item_display_num: config.trait_item_display_num }; + let label = def.label(db, hover_config); let docs = def.docs(db, famous_defs); let value = (|| match def { Definition::Variant(it) => { diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 2df4ca5810b2..e2278fe4b3ab 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -17,7 +17,7 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig { documentation: true, format: HoverDocFormat::Markdown, keywords: true, - trait_item_display_on_hover: Some(7), + trait_item_display_num: Some(7), }; fn check_hover_no_result(ra_fixture: &str) { diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index 8d5f5e1bf677..8d6e161c1b97 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -4,7 +4,7 @@ use hir::{db::HirDatabase, Crate, HirFileIdExt, Module, Semantics}; use ide_db::{ base_db::{FileId, FileRange, SourceDatabaseExt}, - defs::Definition, + defs::{Definition, HoverDisplayConfig}, documentation::Documentation, famous_defs::FamousDefs, helpers::get_definition, @@ -166,7 +166,7 @@ impl StaticIndex<'_> { documentation: true, keywords: true, format: crate::HoverDocFormat::Markdown, - trait_item_display_on_hover: Some(7) + trait_item_display_num: None, }; let tokens = tokens.filter(|token| { matches!( @@ -197,7 +197,7 @@ impl StaticIndex<'_> { enclosing_moniker: current_crate .zip(def.enclosing_definition(self.db)) .and_then(|(cc, enclosing_def)| def_to_moniker(self.db, enclosing_def, cc)), - signature: Some(def.label(self.db, hover_config.trait_item_display_on_hover)), + signature: Some(def.label(self.db, HoverDisplayConfig::default())), kind: def_to_kind(self.db, def), }); self.def_map.insert(def, it); diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 230a0385cdb3..40a2077cb185 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -591,7 +591,7 @@ config_data! { signatureInfo_documentation_enable: bool = "true", /// How many trait item display on hover. - trait_item_display_on_hover: Option = "7", + traitItemDisplayNum: Option = "7", /// Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list. typing_autoClosingAngleBrackets_enable: bool = "false", @@ -1685,7 +1685,7 @@ impl Config { } }, keywords: self.data.hover_documentation_keywords_enable, - trait_item_display_on_hover: self.data.trait_item_display_on_hover, + trait_item_display_num: self.data.traitItemDisplayNum, } } diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 9f3ab4513294..7d005828b8c6 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -927,7 +927,7 @@ Show full signature of the callable. Only shows parameters if disabled. -- Show documentation. -- -[[rust-analyzer.trait.item.display.on.hover]]rust-analyzer.trait.item.display.on.hover (default: `7`):: +[[rust-analyzer.traitItemDisplayNum]]rust-analyzer.traitItemDisplayNum (default: `7`):: + -- How many trait item display on hover. diff --git a/editors/code/package.json b/editors/code/package.json index a4f54ae4f458..b68ab66cdab6 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -1648,7 +1648,7 @@ "default": true, "type": "boolean" }, - "rust-analyzer.trait.item.display.on.hover": { + "rust-analyzer.traitItemDisplayNum": { "markdownDescription": "How many trait item display on hover.", "default": 7, "type": [ From ce4ae41605f8a049afee8b013121496aa9950e9f Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 27 Feb 2024 12:21:05 +0800 Subject: [PATCH 05/69] internal: simplify the process of inserting spaces after mut --- .../ide-assists/src/handlers/inline_call.rs | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs index 11b22b65205b..7531dd5c035d 100644 --- a/crates/ide-assists/src/handlers/inline_call.rs +++ b/crates/ide-assists/src/handlers/inline_call.rs @@ -415,24 +415,16 @@ fn inline( let expr: &ast::Expr = expr; let mut insert_let_stmt = || { - let param_ty = match param_ty { - None => None, - Some(param_ty) => { - if sema.hir_file_for(param_ty.syntax()).is_macro() { - if let Some(param_ty) = - ast::Type::cast(insert_ws_into(param_ty.syntax().clone())) - { - Some(param_ty) - } else { - Some(param_ty.clone_for_update()) - } - } else { - Some(param_ty.clone_for_update()) - } + let param_ty = param_ty.clone().map(|param_ty| { + if sema.hir_file_for(param_ty.syntax()).is_macro() { + ast::Type::cast(insert_ws_into(param_ty.syntax().clone())) + .unwrap_or_else(|| param_ty) + } else { + param_ty } - }; - let ty: Option = - sema.type_of_expr(expr).filter(TypeInfo::has_adjustment).and(param_ty); + }); + + let ty = sema.type_of_expr(expr).filter(TypeInfo::has_adjustment).and(param_ty); let is_self = param .name(sema.db) From 48966268fcf560d8c132edea3b1028fa177d78b8 Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 27 Feb 2024 12:22:17 +0800 Subject: [PATCH 06/69] fix: use 4 spaces for indentation in macro expansion --- .../src/syntax_helpers/insert_whitespace_into_node.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs b/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs index 0b0fc6693526..97b6d4a572a2 100644 --- a/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs +++ b/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs @@ -20,7 +20,7 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode { let after = Position::after; let do_indent = |pos: fn(_) -> Position, token: &SyntaxToken, indent| { - (pos(token.clone()), make::tokens::whitespace(&" ".repeat(2 * indent))) + (pos(token.clone()), make::tokens::whitespace(&" ".repeat(4 * indent))) }; let do_ws = |pos: fn(_) -> Position, token: &SyntaxToken| { (pos(token.clone()), make::tokens::single_space()) @@ -41,7 +41,7 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode { if indent > 0 { mods.push(( Position::after(node.clone()), - make::tokens::whitespace(&" ".repeat(2 * indent)), + make::tokens::whitespace(&" ".repeat(4 * indent)), )); } if node.parent().is_some() { @@ -91,10 +91,7 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode { LIFETIME_IDENT if is_next(is_text, true) => { mods.push(do_ws(after, tok)); } - MUT_KW if is_next(|it| it == SELF_KW, false) => { - mods.push(do_ws(after, tok)); - } - AS_KW | DYN_KW | IMPL_KW | CONST_KW => { + AS_KW | DYN_KW | IMPL_KW | CONST_KW | MUT_KW => { mods.push(do_ws(after, tok)); } T![;] if is_next(|it| it != R_CURLY, true) => { From ec5236f3a8f9ea29abe36e173d9b087f5ede629c Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 27 Feb 2024 12:23:15 +0800 Subject: [PATCH 07/69] test: use 4 spaces for indetation in macro expansion --- .../ide-assists/src/handlers/inline_call.rs | 8 +-- .../ide-assists/src/handlers/inline_macro.rs | 10 ++-- crates/ide/src/expand_macro.rs | 58 +++++++++---------- crates/ide/src/hover/tests.rs | 6 +- 4 files changed, 41 insertions(+), 41 deletions(-) diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs index 7531dd5c035d..ab19779f4e84 100644 --- a/crates/ide-assists/src/handlers/inline_call.rs +++ b/crates/ide-assists/src/handlers/inline_call.rs @@ -1348,8 +1348,8 @@ macro_rules! define_foo { define_foo!(); fn bar() -> u32 { { - let x = 0; - x + let x = 0; + x } } "#, @@ -1662,7 +1662,7 @@ fn main() { let a: A = A{}; let b = { let a = a; - a as A + a as A }; } "#, @@ -1781,7 +1781,7 @@ fn _hash2(self_: &u64, state: &mut u64) { { let inner_self_: &u64 = &self_; let state: &mut u64 = state; - _write_u64(state, *inner_self_) + _write_u64(state, *inner_self_) }; } "#, diff --git a/crates/ide-assists/src/handlers/inline_macro.rs b/crates/ide-assists/src/handlers/inline_macro.rs index 0c9e971dd23c..4708be616964 100644 --- a/crates/ide-assists/src/handlers/inline_macro.rs +++ b/crates/ide-assists/src/handlers/inline_macro.rs @@ -288,11 +288,11 @@ macro_rules! foo { } fn main() { cfg_if!{ - if #[cfg(test)]{ - 1; - }else { - 1; - } + if #[cfg(test)]{ + 1; + }else { + 1; + } }; } "#, diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs index 17c701ad0359..9eb5a9db6250 100644 --- a/crates/ide/src/expand_macro.rs +++ b/crates/ide/src/expand_macro.rs @@ -308,8 +308,8 @@ f$0oo!(); expect![[r#" foo! fn some_thing() -> u32 { - let a = 0; - a+10 + let a = 0; + a+10 }"#]], ); } @@ -342,13 +342,13 @@ fn main() { expect![[r#" match_ast! { - if let Some(it) = ast::TraitDef::cast(container.clone()){} - else if let Some(it) = ast::ImplDef::cast(container.clone()){} - else { - { - continue + if let Some(it) = ast::TraitDef::cast(container.clone()){} + else if let Some(it) = ast::ImplDef::cast(container.clone()){} + else { + { + continue + } } - } }"#]], ); } @@ -397,12 +397,12 @@ fn main() { expect![[r#" foo! { - macro_rules! bar { - () => { - 42 + macro_rules! bar { + () => { + 42 + } } - } - 42 + 42 }"#]], ); } @@ -482,16 +482,16 @@ struct Foo {} expect![[r#" Clone impl < >$crate::clone::Clone for Foo< >where { - fn clone(&self) -> Self { - match self { - Foo{} - => Foo{} - , + fn clone(&self) -> Self { + match self { + Foo{} + => Foo{} + , - } - } + } + } - }"#]], + }"#]], ); } @@ -534,16 +534,16 @@ struct Foo {} expect![[r#" Clone impl < >$crate::clone::Clone for Foo< >where { - fn clone(&self) -> Self { - match self { - Foo{} - => Foo{} - , + fn clone(&self) -> Self { + match self { + Foo{} + => Foo{} + , - } - } + } + } - }"#]], + }"#]], ); } } diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index ead4f91595f0..7ecfdfb1942f 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -6341,8 +6341,8 @@ fn main() { $0V; } ```rust pub const V: i8 = { - let e = 123; - f(e) + let e = 123; + f(e) } ``` "#]], @@ -6368,7 +6368,7 @@ fn main() { $0V; } ```rust pub static V: i8 = { - let e = 123; + let e = 123; } ``` "#]], From 76b86b24bd38e53ee8a3555608339803ecb5cbb9 Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 27 Feb 2024 13:54:52 +0800 Subject: [PATCH 08/69] fix: clippy and format --- crates/ide-assists/src/handlers/inline_call.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs index ab19779f4e84..9c4f3bb93708 100644 --- a/crates/ide-assists/src/handlers/inline_call.rs +++ b/crates/ide-assists/src/handlers/inline_call.rs @@ -417,8 +417,7 @@ fn inline( let mut insert_let_stmt = || { let param_ty = param_ty.clone().map(|param_ty| { if sema.hir_file_for(param_ty.syntax()).is_macro() { - ast::Type::cast(insert_ws_into(param_ty.syntax().clone())) - .unwrap_or_else(|| param_ty) + ast::Type::cast(insert_ws_into(param_ty.syntax().clone())).unwrap_or(param_ty) } else { param_ty } From 6112ddfabbc27cfa3c6d68a93d37f161cf7b5caa Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Wed, 28 Feb 2024 10:13:31 +0100 Subject: [PATCH 09/69] Add prefix `file_` to `Semantics`'s `to_module_defs()`/`to_module_def()` methods --- crates/hir/src/semantics.rs | 10 +++++----- crates/hir/src/semantics/source_to_def.rs | 2 +- .../src/handlers/generate_delegate_trait.rs | 2 +- crates/ide-assists/src/handlers/move_from_mod_rs.rs | 2 +- crates/ide-assists/src/handlers/move_to_mod_rs.rs | 2 +- crates/ide-db/src/helpers.rs | 2 +- crates/ide-diagnostics/src/handlers/missing_fields.rs | 2 +- crates/ide-diagnostics/src/lib.rs | 2 +- crates/ide/src/parent_module.rs | 2 +- crates/ide/src/rename.rs | 2 +- crates/ide/src/runnables.rs | 2 +- crates/ide/src/syntax_highlighting.rs | 2 +- 12 files changed, 16 insertions(+), 16 deletions(-) diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 1fb6570b6a40..6aa053b5ac6e 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -223,12 +223,12 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { self.imp.resolve_variant(record_lit).map(VariantDef::from) } - pub fn to_module_def(&self, file: FileId) -> Option { - self.imp.to_module_def(file).next() + pub fn file_to_module_def(&self, file: FileId) -> Option { + self.imp.file_to_module_defs(file).next() } - pub fn to_module_defs(&self, file: FileId) -> impl Iterator { - self.imp.to_module_def(file) + pub fn file_to_module_defs(&self, file: FileId) -> impl Iterator { + self.imp.file_to_module_defs(file) } pub fn to_struct_def(&self, s: &ast::Struct) -> Option { @@ -1237,7 +1237,7 @@ impl<'db> SemanticsImpl<'db> { T::to_def(self, src) } - fn to_module_def(&self, file: FileId) -> impl Iterator { + fn file_to_module_defs(&self, file: FileId) -> impl Iterator { self.with_ctx(|ctx| ctx.file_to_def(file)).into_iter().map(Module::from) } diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index ef4ed90ce35f..4733ea5a35b9 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs @@ -118,7 +118,7 @@ pub(super) struct SourceToDefCtx<'a, 'b> { impl SourceToDefCtx<'_, '_> { pub(super) fn file_to_def(&self, file: FileId) -> SmallVec<[ModuleId; 1]> { - let _p = tracing::span!(tracing::Level::INFO, "SourceBinder::to_module_def"); + let _p = tracing::span!(tracing::Level::INFO, "SourceBinder::file_to_module_def"); let mut mods = SmallVec::new(); for &crate_id in self.db.relevant_crates(file).iter() { // FIXME: inner items diff --git a/crates/ide-assists/src/handlers/generate_delegate_trait.rs b/crates/ide-assists/src/handlers/generate_delegate_trait.rs index 7a60287f923f..e0bcd78c99ba 100644 --- a/crates/ide-assists/src/handlers/generate_delegate_trait.rs +++ b/crates/ide-assists/src/handlers/generate_delegate_trait.rs @@ -116,7 +116,7 @@ impl Field { ) -> Option { let db = ctx.sema.db; - let module = ctx.sema.to_module_def(ctx.file_id())?; + let module = ctx.sema.file_to_module_def(ctx.file_id())?; let (name, range, ty) = match f { Either::Left(f) => { diff --git a/crates/ide-assists/src/handlers/move_from_mod_rs.rs b/crates/ide-assists/src/handlers/move_from_mod_rs.rs index 917d0b3671e8..a256f60c421c 100644 --- a/crates/ide-assists/src/handlers/move_from_mod_rs.rs +++ b/crates/ide-assists/src/handlers/move_from_mod_rs.rs @@ -25,7 +25,7 @@ use crate::{ // ``` pub(crate) fn move_from_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let source_file = ctx.find_node_at_offset::()?; - let module = ctx.sema.to_module_def(ctx.file_id())?; + let module = ctx.sema.file_to_module_def(ctx.file_id())?; // Enable this assist if the user select all "meaningful" content in the source file let trimmed_selected_range = trimmed_text_range(&source_file, ctx.selection_trimmed()); let trimmed_file_range = trimmed_text_range(&source_file, source_file.syntax().text_range()); diff --git a/crates/ide-assists/src/handlers/move_to_mod_rs.rs b/crates/ide-assists/src/handlers/move_to_mod_rs.rs index b73270cd05fb..a8a124eebb68 100644 --- a/crates/ide-assists/src/handlers/move_to_mod_rs.rs +++ b/crates/ide-assists/src/handlers/move_to_mod_rs.rs @@ -25,7 +25,7 @@ use crate::{ // ``` pub(crate) fn move_to_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let source_file = ctx.find_node_at_offset::()?; - let module = ctx.sema.to_module_def(ctx.file_id())?; + let module = ctx.sema.file_to_module_def(ctx.file_id())?; // Enable this assist if the user select all "meaningful" content in the source file let trimmed_selected_range = trimmed_text_range(&source_file, ctx.selection_trimmed()); let trimmed_file_range = trimmed_text_range(&source_file, source_file.syntax().text_range()); diff --git a/crates/ide-db/src/helpers.rs b/crates/ide-db/src/helpers.rs index 0b5ad7060e04..4ac8a7c4c4aa 100644 --- a/crates/ide-db/src/helpers.rs +++ b/crates/ide-db/src/helpers.rs @@ -64,7 +64,7 @@ pub fn visit_file_defs( cb: &mut dyn FnMut(Definition), ) { let db = sema.db; - let module = match sema.to_module_def(file_id) { + let module = match sema.file_to_module_def(file_id) { Some(it) => it, None => return, }; diff --git a/crates/ide-diagnostics/src/handlers/missing_fields.rs b/crates/ide-diagnostics/src/handlers/missing_fields.rs index 09daefd084dc..f92ba576d3ab 100644 --- a/crates/ide-diagnostics/src/handlers/missing_fields.rs +++ b/crates/ide-diagnostics/src/handlers/missing_fields.rs @@ -200,7 +200,7 @@ fn get_default_constructor( } } - let krate = ctx.sema.to_module_def(d.file.original_file(ctx.sema.db))?.krate(); + let krate = ctx.sema.file_to_module_def(d.file.original_file(ctx.sema.db))?.krate(); let module = krate.root_module(); // Look for a ::new() associated function diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs index 9f4368b04e79..6c72dbb5edf9 100644 --- a/crates/ide-diagnostics/src/lib.rs +++ b/crates/ide-diagnostics/src/lib.rs @@ -315,7 +315,7 @@ pub fn diagnostics( handlers::json_is_not_rust::json_in_items(&sema, &mut res, file_id, &node, config); } - let module = sema.to_module_def(file_id); + let module = sema.file_to_module_def(file_id); let ctx = DiagnosticsContext { config, sema, resolve }; if module.is_none() { diff --git a/crates/ide/src/parent_module.rs b/crates/ide/src/parent_module.rs index f67aea2d5b9c..ce7a6779e27c 100644 --- a/crates/ide/src/parent_module.rs +++ b/crates/ide/src/parent_module.rs @@ -48,7 +48,7 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec sema - .to_module_defs(position.file_id) + .file_to_module_defs(position.file_id) .flat_map(|module| NavigationTarget::from_module_to_decl(db, module)) .collect(), } diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs index f78153df38bd..8c2ae327c7fc 100644 --- a/crates/ide/src/rename.rs +++ b/crates/ide/src/rename.rs @@ -156,7 +156,7 @@ pub(crate) fn will_rename_file( new_name_stem: &str, ) -> Option { let sema = Semantics::new(db); - let module = sema.to_module_def(file_id)?; + let module = sema.file_to_module_def(file_id)?; let def = Definition::Module(module); let mut change = if is_raw_identifier(new_name_stem) { def.rename(&sema, &SmolStr::from_iter(["r#", new_name_stem])).ok()? diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index ae107a96040d..5fe46444ff41 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs @@ -178,7 +178,7 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec { } }); - sema.to_module_defs(file_id) + sema.file_to_module_defs(file_id) .map(|it| runnable_mod_outline_definition(&sema, it)) .for_each(|it| add_opt(it, None)); diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index dfcbaf54d4f9..d2bd3bab14e4 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs @@ -223,7 +223,7 @@ fn traverse( krate: hir::Crate, range_to_highlight: TextRange, ) { - let is_unlinked = sema.to_module_def(file_id).is_none(); + let is_unlinked = sema.file_to_module_def(file_id).is_none(); let mut bindings_shadow_count: FxHashMap = FxHashMap::default(); enum AttrOrDerive { From fac8a14de874d36aed74e3e29022342f77b0c01d Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Wed, 28 Feb 2024 10:25:01 +0100 Subject: [PATCH 10/69] Add a more methods for resolving definitions from AST to their corresponding HIR types --- crates/hir/src/semantics.rs | 61 +++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 6aa053b5ac6e..ccbc0f834684 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -38,10 +38,11 @@ use crate::{ db::HirDatabase, semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, source_analyzer::{resolve_hir_path, SourceAnalyzer}, - Access, Adjust, Adjustment, AutoBorrow, BindingMode, BuiltinAttr, Callable, ConstParam, Crate, - DeriveHelper, Field, Function, HasSource, HirFileId, Impl, InFile, Label, LifetimeParam, Local, - Macro, Module, ModuleDef, Name, OverloadedDeref, Path, ScopeDef, Struct, ToolModule, Trait, - TupleField, Type, TypeAlias, TypeParam, VariantDef, + Access, Adjust, Adjustment, Adt, AutoBorrow, BindingMode, BuiltinAttr, Callable, Const, + ConstParam, Crate, DeriveHelper, Enum, Field, Function, HasSource, HirFileId, Impl, InFile, + Label, LifetimeParam, Local, Macro, Module, ModuleDef, Name, OverloadedDeref, Path, ScopeDef, + Static, Struct, ToolModule, Trait, TraitAlias, TupleField, Type, TypeAlias, TypeParam, Union, + Variant, VariantDef, }; pub enum DescendPreference { @@ -231,13 +232,61 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { self.imp.file_to_module_defs(file) } - pub fn to_struct_def(&self, s: &ast::Struct) -> Option { - self.imp.to_def(s).map(Struct::from) + pub fn to_adt_def(&self, a: &ast::Adt) -> Option { + self.imp.to_def(a).map(Adt::from) + } + + pub fn to_const_def(&self, c: &ast::Const) -> Option { + self.imp.to_def(c).map(Const::from) + } + + pub fn to_enum_def(&self, e: &ast::Enum) -> Option { + self.imp.to_def(e).map(Enum::from) + } + + pub fn to_enum_variant_def(&self, v: &ast::Variant) -> Option { + self.imp.to_def(v).map(Variant::from) + } + + pub fn to_fn_def(&self, f: &ast::Fn) -> Option { + self.imp.to_def(f).map(Function::from) } pub fn to_impl_def(&self, i: &ast::Impl) -> Option { self.imp.to_def(i).map(Impl::from) } + + pub fn to_macro_def(&self, m: &ast::Macro) -> Option { + self.imp.to_def(m).map(Macro::from) + } + + pub fn to_module_def(&self, m: &ast::Module) -> Option { + self.imp.to_def(m).map(Module::from) + } + + pub fn to_static_def(&self, s: &ast::Static) -> Option { + self.imp.to_def(s).map(Static::from) + } + + pub fn to_struct_def(&self, s: &ast::Struct) -> Option { + self.imp.to_def(s).map(Struct::from) + } + + pub fn to_trait_alias_def(&self, t: &ast::TraitAlias) -> Option { + self.imp.to_def(t).map(TraitAlias::from) + } + + pub fn to_trait_def(&self, t: &ast::Trait) -> Option { + self.imp.to_def(t).map(Trait::from) + } + + pub fn to_type_alias_def(&self, t: &ast::TypeAlias) -> Option { + self.imp.to_def(t).map(TypeAlias::from) + } + + pub fn to_union_def(&self, u: &ast::Union) -> Option { + self.imp.to_def(u).map(Union::from) + } } impl<'db> SemanticsImpl<'db> { From 03b02e6bd0c61fc800c0694e1156690e9e2a142c Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 28 Feb 2024 16:17:44 +0100 Subject: [PATCH 11/69] internal: Move ide-assists codegen tests into an xtask codegen command --- .cargo/config.toml | 1 + .github/workflows/ci.yaml | 3 + Cargo.lock | 2 +- crates/ide-assists/Cargo.toml | 1 - crates/ide-assists/src/tests.rs | 2 - xtask/Cargo.toml | 3 +- xtask/src/codegen.rs | 211 ++++++++++++++++++ .../src/codegen/assists_doc_tests.rs | 26 ++- xtask/src/flags.rs | 29 +++ xtask/src/main.rs | 18 +- xtask/src/release.rs | 6 +- 11 files changed, 273 insertions(+), 29 deletions(-) create mode 100644 xtask/src/codegen.rs rename crates/ide-assists/src/tests/sourcegen.rs => xtask/src/codegen/assists_doc_tests.rs (89%) diff --git a/.cargo/config.toml b/.cargo/config.toml index c3cfda85517e..070560dfbc31 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -3,6 +3,7 @@ xtask = "run --package xtask --bin xtask --" tq = "test -- -q" qt = "tq" lint = "clippy --all-targets -- --cap-lints warn" +codegen = "run --package xtask --bin xtask -- codegen" [target.x86_64-pc-windows-msvc] linker = "rust-lld" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5a8b18e3fe1b..2d8946520d5e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -79,6 +79,9 @@ jobs: if: matrix.os == 'ubuntu-latest' run: sed -i '/\[profile.dev]/a opt-level=1' Cargo.toml + - name: Codegen checks (rust-analyzer) + run: cargo codegen --check + - name: Compile (tests) run: cargo test --no-run --locked ${{ env.USE_SYSROOT_ABI }} diff --git a/Cargo.lock b/Cargo.lock index 3c87291dbadb..0bdd4821139c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -676,7 +676,6 @@ dependencies = [ "itertools", "profile", "smallvec", - "sourcegen", "stdx", "syntax", "test-fixture", @@ -2502,6 +2501,7 @@ version = "0.1.0" dependencies = [ "anyhow", "flate2", + "stdx", "time", "write-json", "xflags", diff --git a/crates/ide-assists/Cargo.toml b/crates/ide-assists/Cargo.toml index 98961a18de25..d84fa7dffc54 100644 --- a/crates/ide-assists/Cargo.toml +++ b/crates/ide-assists/Cargo.toml @@ -33,7 +33,6 @@ expect-test = "1.4.0" # local deps test-utils.workspace = true test-fixture.workspace = true -sourcegen.workspace = true [features] in-rust-tree = [] diff --git a/crates/ide-assists/src/tests.rs b/crates/ide-assists/src/tests.rs index 9b6f7d018ee3..32d698410208 100644 --- a/crates/ide-assists/src/tests.rs +++ b/crates/ide-assists/src/tests.rs @@ -1,6 +1,4 @@ mod generated; -#[cfg(not(feature = "in-rust-tree"))] -mod sourcegen; use expect_test::expect; use hir::Semantics; diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 863a63ac82e7..5e758e0190ce 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -14,7 +14,8 @@ xshell.workspace = true xflags = "0.3.0" time = { version = "0.3", default-features = false } zip = { version = "0.6", default-features = false, features = ["deflate", "time"] } +stdx.workspace = true # Avoid adding more dependencies to this crate [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs new file mode 100644 index 000000000000..e579660ac9b1 --- /dev/null +++ b/xtask/src/codegen.rs @@ -0,0 +1,211 @@ +use std::{ + fmt, fs, mem, + path::{Path, PathBuf}, +}; + +use xshell::{cmd, Shell}; + +use crate::{flags, project_root}; + +pub(crate) mod assists_doc_tests; + +impl flags::Codegen { + pub(crate) fn run(self, _sh: &Shell) -> anyhow::Result<()> { + match self.codegen_type.unwrap_or_default() { + flags::CodegenType::All => { + assists_doc_tests::generate(self.check); + } + flags::CodegenType::AssistsDocTests => assists_doc_tests::generate(self.check), + } + Ok(()) + } +} + +fn list_rust_files(dir: &Path) -> Vec { + let mut res = list_files(dir); + res.retain(|it| { + it.file_name().unwrap_or_default().to_str().unwrap_or_default().ends_with(".rs") + }); + res +} + +fn list_files(dir: &Path) -> Vec { + let mut res = Vec::new(); + let mut work = vec![dir.to_path_buf()]; + while let Some(dir) = work.pop() { + for entry in dir.read_dir().unwrap() { + let entry = entry.unwrap(); + let file_type = entry.file_type().unwrap(); + let path = entry.path(); + let is_hidden = + path.file_name().unwrap_or_default().to_str().unwrap_or_default().starts_with('.'); + if !is_hidden { + if file_type.is_dir() { + work.push(path); + } else if file_type.is_file() { + res.push(path); + } + } + } + } + res +} + +#[derive(Clone)] +pub(crate) struct CommentBlock { + pub(crate) id: String, + pub(crate) line: usize, + pub(crate) contents: Vec, + is_doc: bool, +} + +impl CommentBlock { + fn extract(tag: &str, text: &str) -> Vec { + assert!(tag.starts_with(char::is_uppercase)); + + let tag = format!("{tag}:"); + let mut blocks = CommentBlock::extract_untagged(text); + blocks.retain_mut(|block| { + let first = block.contents.remove(0); + let Some(id) = first.strip_prefix(&tag) else { + return false; + }; + + if block.is_doc { + panic!("Use plain (non-doc) comments with tags like {tag}:\n {first}"); + } + + block.id = id.trim().to_owned(); + true + }); + blocks + } + + fn extract_untagged(text: &str) -> Vec { + let mut res = Vec::new(); + + let lines = text.lines().map(str::trim_start); + + let dummy_block = + CommentBlock { id: String::new(), line: 0, contents: Vec::new(), is_doc: false }; + let mut block = dummy_block.clone(); + for (line_num, line) in lines.enumerate() { + match line.strip_prefix("//") { + Some(mut contents) => { + if let Some('/' | '!') = contents.chars().next() { + contents = &contents[1..]; + block.is_doc = true; + } + if let Some(' ') = contents.chars().next() { + contents = &contents[1..]; + } + block.contents.push(contents.to_owned()); + } + None => { + if !block.contents.is_empty() { + let block = mem::replace(&mut block, dummy_block.clone()); + res.push(block); + } + block.line = line_num + 2; + } + } + } + if !block.contents.is_empty() { + res.push(block); + } + res + } +} + +#[derive(Debug)] +pub(crate) struct Location { + pub(crate) file: PathBuf, + pub(crate) line: usize, +} + +impl fmt::Display for Location { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let path = self.file.strip_prefix(project_root()).unwrap().display().to_string(); + let path = path.replace('\\', "/"); + let name = self.file.file_name().unwrap(); + write!( + f, + "https://github.com/rust-lang/rust-analyzer/blob/master/{}#L{}[{}]", + path, + self.line, + name.to_str().unwrap() + ) + } +} + +fn ensure_rustfmt(sh: &Shell) { + let version = cmd!(sh, "rustup run stable rustfmt --version").read().unwrap_or_default(); + if !version.contains("stable") { + panic!( + "Failed to run rustfmt from toolchain 'stable'. \ + Please run `rustup component add rustfmt --toolchain stable` to install it.", + ); + } +} + +fn reformat(text: String) -> String { + let sh = Shell::new().unwrap(); + ensure_rustfmt(&sh); + let rustfmt_toml = project_root().join("rustfmt.toml"); + let mut stdout = cmd!( + sh, + "rustup run stable rustfmt --config-path {rustfmt_toml} --config fn_single_line=true" + ) + .stdin(text) + .read() + .unwrap(); + if !stdout.ends_with('\n') { + stdout.push('\n'); + } + stdout +} + +fn add_preamble(generator: &'static str, mut text: String) -> String { + let preamble = format!("//! Generated by `{generator}`, do not edit by hand.\n\n"); + text.insert_str(0, &preamble); + text +} + +/// Checks that the `file` has the specified `contents`. If that is not the +/// case, updates the file and then fails the test. +#[allow(clippy::print_stderr)] +fn ensure_file_contents(file: &Path, contents: &str, check: bool) { + if let Ok(old_contents) = fs::read_to_string(file) { + if normalize_newlines(&old_contents) == normalize_newlines(contents) { + // File is already up to date. + return; + } + } + + let display_path = file.strip_prefix(project_root()).unwrap_or(file); + if check { + panic!( + "{} was not up-to-date{}", + file.display(), + if std::env::var("CI").is_ok() { + "\n NOTE: run `cargo codegen` locally and commit the updated files\n" + } else { + "" + } + ); + } else { + eprintln!( + "\n\x1b[31;1merror\x1b[0m: {} was not up-to-date, updating\n", + display_path.display() + ); + + if let Some(parent) = file.parent() { + let _ = fs::create_dir_all(parent); + } + fs::write(file, contents).unwrap(); + } +} + +fn normalize_newlines(s: &str) -> String { + s.replace("\r\n", "\n") +} diff --git a/crates/ide-assists/src/tests/sourcegen.rs b/xtask/src/codegen/assists_doc_tests.rs similarity index 89% rename from crates/ide-assists/src/tests/sourcegen.rs rename to xtask/src/codegen/assists_doc_tests.rs index 847cb1af51e0..b2d89dde7659 100644 --- a/crates/ide-assists/src/tests/sourcegen.rs +++ b/xtask/src/codegen/assists_doc_tests.rs @@ -3,10 +3,15 @@ use std::{fmt, fs, path::Path}; use stdx::format_to_acc; -use test_utils::project_root; -#[test] -fn sourcegen_assists_docs() { +use crate::{ + codegen::{ + add_preamble, ensure_file_contents, list_rust_files, reformat, CommentBlock, Location, + }, + project_root, +}; + +pub(crate) fn generate(check: bool) { let assists = Assist::collect(); { @@ -40,10 +45,11 @@ r#####" buf.push_str(&test) } } - let buf = sourcegen::add_preamble("sourcegen_assists_docs", sourcegen::reformat(buf)); - sourcegen::ensure_file_contents( + let buf = add_preamble("sourcegen_assists_docs", reformat(buf)); + ensure_file_contents( &project_root().join("crates/ide-assists/src/tests/generated.rs"), &buf, + check, ); } @@ -52,7 +58,7 @@ r#####" // git repo. Instead, `cargo xtask release` runs this test before making // a release. - let contents = sourcegen::add_preamble( + let contents = add_preamble( "sourcegen_assists_docs", assists.into_iter().map(|it| it.to_string()).collect::>().join("\n\n"), ); @@ -71,7 +77,7 @@ struct Section { #[derive(Debug)] struct Assist { id: String, - location: sourcegen::Location, + location: Location, sections: Vec
, } @@ -80,7 +86,7 @@ impl Assist { let handlers_dir = project_root().join("crates/ide-assists/src/handlers"); let mut res = Vec::new(); - for path in sourcegen::list_rust_files(&handlers_dir) { + for path in list_rust_files(&handlers_dir) { collect_file(&mut res, path.as_path()); } res.sort_by(|lhs, rhs| lhs.id.cmp(&rhs.id)); @@ -88,7 +94,7 @@ impl Assist { fn collect_file(acc: &mut Vec, path: &Path) { let text = fs::read_to_string(path).unwrap(); - let comment_blocks = sourcegen::CommentBlock::extract("Assist", &text); + let comment_blocks = CommentBlock::extract("Assist", &text); for block in comment_blocks { let id = block.id; @@ -97,7 +103,7 @@ impl Assist { "invalid assist id: {id:?}" ); let mut lines = block.contents.iter().peekable(); - let location = sourcegen::Location { file: path.to_path_buf(), line: block.line }; + let location = Location { file: path.to_path_buf(), line: block.line }; let mut assist = Assist { id, location, sections: Vec::new() }; while lines.peek().is_some() { diff --git a/xtask/src/flags.rs b/xtask/src/flags.rs index e234090a07ce..f5827170b651 100644 --- a/xtask/src/flags.rs +++ b/xtask/src/flags.rs @@ -52,6 +52,11 @@ xflags::xflags! { cmd bb { required suffix: String } + + cmd codegen { + optional codegen_type: CodegenType + optional --check + } } } @@ -73,8 +78,32 @@ pub enum XtaskCmd { PublishReleaseNotes(PublishReleaseNotes), Metrics(Metrics), Bb(Bb), + Codegen(Codegen), +} + +#[derive(Debug)] +pub struct Codegen { + pub check: bool, + pub codegen_type: Option, +} + +#[derive(Debug, Default)] +pub enum CodegenType { + #[default] + All, + AssistsDocTests, } +impl FromStr for CodegenType { + type Err = String; + fn from_str(s: &str) -> Result { + match s { + "all" => Ok(Self::All), + "assists-doc-tests" => Ok(Self::AssistsDocTests), + _ => Err("Invalid option".to_owned()), + } + } +} #[derive(Debug)] pub struct Install { pub client: bool, diff --git a/xtask/src/main.rs b/xtask/src/main.rs index df4d9810e6f1..9418675a348c 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -13,6 +13,7 @@ mod flags; +mod codegen; mod dist; mod install; mod metrics; @@ -20,10 +21,7 @@ mod publish; mod release; use anyhow::bail; -use std::{ - env, - path::{Path, PathBuf}, -}; +use std::{env, path::PathBuf}; use xshell::{cmd, Shell}; fn main() -> anyhow::Result<()> { @@ -40,6 +38,7 @@ fn main() -> anyhow::Result<()> { flags::XtaskCmd::Dist(cmd) => cmd.run(sh), flags::XtaskCmd::PublishReleaseNotes(cmd) => cmd.run(sh), flags::XtaskCmd::Metrics(cmd) => cmd.run(sh), + flags::XtaskCmd::Codegen(cmd) => cmd.run(sh), flags::XtaskCmd::Bb(cmd) => { { let _d = sh.push_dir("./crates/rust-analyzer"); @@ -54,14 +53,11 @@ fn main() -> anyhow::Result<()> { } } +/// Returns the path to the root directory of `rust-analyzer` project. fn project_root() -> PathBuf { - Path::new( - &env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned()), - ) - .ancestors() - .nth(1) - .unwrap() - .to_path_buf() + let dir = + env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned()); + PathBuf::from(dir).parent().unwrap().to_owned() } fn run_fuzzer(sh: &Shell) -> anyhow::Result<()> { diff --git a/xtask/src/release.rs b/xtask/src/release.rs index 4a3069147785..f99f9ecbc39d 100644 --- a/xtask/src/release.rs +++ b/xtask/src/release.rs @@ -2,7 +2,7 @@ mod changelog; use xshell::{cmd, Shell}; -use crate::{date_iso, flags, is_release_tag, project_root}; +use crate::{codegen, date_iso, flags, is_release_tag, project_root}; impl flags::Release { pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> { @@ -23,8 +23,8 @@ impl flags::Release { } // Generates bits of manual.adoc. - cmd!(sh, "cargo test -p ide-assists -p ide-diagnostics -p rust-analyzer -- sourcegen_") - .run()?; + cmd!(sh, "cargo test -p ide-diagnostics -p rust-analyzer -- sourcegen_").run()?; + codegen::assists_doc_tests::generate(false); let website_root = project_root().join("../rust-analyzer.github.io"); { From a01e4f8b72ccea318e5fb98c8f0cc2cab2c212b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 29 Feb 2024 16:00:29 +0200 Subject: [PATCH 12/69] Add basic support for Native Debug --- editors/code/src/debug.ts | 60 ++++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/editors/code/src/debug.ts b/editors/code/src/debug.ts index d9c6b6ac4566..3fc63fc7d81a 100644 --- a/editors/code/src/debug.ts +++ b/editors/code/src/debug.ts @@ -81,8 +81,9 @@ async function getDebugConfiguration( if (!editor) return; const knownEngines: Record = { - "vadimcn.vscode-lldb": getLldbDebugConfig, - "ms-vscode.cpptools": getCppvsDebugConfig, + "ms-vscode.cpptools": getCCppDebugConfig, + "vadimcn.vscode-lldb": getCodeLldbDebugConfig, + "webfreak.debug": getNativeDebugConfig, }; const debugOptions = ctx.config.debug; @@ -97,12 +98,14 @@ async function getDebugConfiguration( } if (!debugEngine) { + const commandCCpp: string = createCommandLink("ms-vscode.cpptools"); const commandCodeLLDB: string = createCommandLink("vadimcn.vscode-lldb"); - const commandCpp: string = createCommandLink("ms-vscode.cpptools"); + const commandNativeDebug: string = createCommandLink("webfreak.debug"); await vscode.window.showErrorMessage( `Install [CodeLLDB](command:${commandCodeLLDB} "Open CodeLLDB")` + - ` or [C/C++](command:${commandCpp} "Open C/C++") extension for debugging.`, + `, [C/C++](command:${commandCCpp} "Open C/C++") ` + + `or [Native Debug](command:${commandNativeDebug} "Open Native Debug") for debugging.`, ); return; } @@ -184,7 +187,7 @@ async function getDebugExecutableInfo( return executableInfo; } -function getLldbDebugConfig( +function getCCppDebugConfig( runnable: ra.Runnable, executable: string, cargoWorkspace: string, @@ -192,19 +195,18 @@ function getLldbDebugConfig( sourceFileMap?: Record, ): vscode.DebugConfiguration { return { - type: "lldb", + type: os.platform() === "win32" ? "cppvsdbg" : "cppdbg", request: "launch", name: runnable.label, program: executable, args: runnable.args.executableArgs, cwd: cargoWorkspace || runnable.args.workspaceRoot, - sourceMap: sourceFileMap, - sourceLanguages: ["rust"], + sourceFileMap, env, }; } -function getCppvsDebugConfig( +function getCodeLldbDebugConfig( runnable: ra.Runnable, executable: string, cargoWorkspace: string, @@ -212,13 +214,49 @@ function getCppvsDebugConfig( sourceFileMap?: Record, ): vscode.DebugConfiguration { return { - type: os.platform() === "win32" ? "cppvsdbg" : "cppdbg", + type: "lldb", request: "launch", name: runnable.label, program: executable, args: runnable.args.executableArgs, cwd: cargoWorkspace || runnable.args.workspaceRoot, - sourceFileMap, + sourceMap: sourceFileMap, + sourceLanguages: ["rust"], env, }; } + +function getNativeDebugConfig( + runnable: ra.Runnable, + executable: string, + cargoWorkspace: string, + env: Record, + _sourceFileMap?: Record, +): vscode.DebugConfiguration { + return { + type: "gdb", + request: "launch", + name: runnable.label, + target: executable, + // See https://github.com/WebFreak001/code-debug/issues/359 + arguments: quote(runnable.args.executableArgs), + cwd: cargoWorkspace || runnable.args.workspaceRoot, + env, + valuesFormatting: "prettyPrinters", + }; +} + +// Based on https://github.com/ljharb/shell-quote/blob/main/quote.js +function quote(xs: string[]) { + return xs + .map(function (s) { + if (/["\s]/.test(s) && !/'/.test(s)) { + return "'" + s.replace(/(['\\])/g, "\\$1") + "'"; + } + if (/["'\s]/.test(s)) { + return '"' + s.replace(/(["\\$`!])/g, "\\$1") + '"'; + } + return s.replace(/([A-Za-z]:)?([#!"$&'()*,:;<=>?@[\\\]^`{|}])/g, "$1\\$2"); + }) + .join(" "); +} From 06a883e32f097398ec3348524555c0fde45fe24a Mon Sep 17 00:00:00 2001 From: mo8it Date: Thu, 29 Feb 2024 16:05:26 +0100 Subject: [PATCH 13/69] Take a reference instead of cloning --- lib/lsp-server/src/req_queue.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/lsp-server/src/req_queue.rs b/lib/lsp-server/src/req_queue.rs index 7b47f5388b5e..347a9fb6fb98 100644 --- a/lib/lsp-server/src/req_queue.rs +++ b/lib/lsp-server/src/req_queue.rs @@ -37,7 +37,7 @@ impl Incoming { } pub fn cancel(&mut self, id: RequestId) -> Option { - let _data = self.complete(id.clone())?; + let _data = self.complete(&id)?; let error = ResponseError { code: ErrorCode::RequestCanceled as i32, message: "canceled by client".to_owned(), @@ -46,8 +46,8 @@ impl Incoming { Some(Response { id, result: None, error: Some(error) }) } - pub fn complete(&mut self, id: RequestId) -> Option { - self.pending.remove(&id) + pub fn complete(&mut self, id: &RequestId) -> Option { + self.pending.remove(id) } pub fn is_completed(&self, id: &RequestId) -> bool { From 748f57c16da357eb1df6e129170354a7d3851130 Mon Sep 17 00:00:00 2001 From: mo8it Date: Thu, 29 Feb 2024 16:28:59 +0100 Subject: [PATCH 14/69] Only clone when required --- crates/rust-analyzer/src/cli/analysis_stats.rs | 12 ++++++------ crates/rust-analyzer/src/global_state.rs | 8 ++++---- crates/rust-analyzer/src/handlers/request.rs | 4 ++-- crates/vfs/src/lib.rs | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index 186b65692ecb..b500db77d950 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -1075,12 +1075,12 @@ fn location_csv_pat(db: &RootDatabase, vfs: &Vfs, sm: &BodySourceMap, pat_id: Pa format!("{path},{}:{},{}:{}", start.line + 1, start.col, end.line + 1, end.col) } -fn expr_syntax_range( +fn expr_syntax_range<'a>( db: &RootDatabase, - vfs: &Vfs, + vfs: &'a Vfs, sm: &BodySourceMap, expr_id: ExprId, -) -> Option<(VfsPath, LineCol, LineCol)> { +) -> Option<(&'a VfsPath, LineCol, LineCol)> { let src = sm.expr_syntax(expr_id); if let Ok(src) = src { let root = db.parse_or_expand(src.file_id); @@ -1096,12 +1096,12 @@ fn expr_syntax_range( None } } -fn pat_syntax_range( +fn pat_syntax_range<'a>( db: &RootDatabase, - vfs: &Vfs, + vfs: &'a Vfs, sm: &BodySourceMap, pat_id: PatId, -) -> Option<(VfsPath, LineCol, LineCol)> { +) -> Option<(&'a VfsPath, LineCol, LineCol)> { let src = sm.pat_syntax(pat_id); if let Ok(src) = src { let root = db.parse_or_expand(src.file_id); diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index b2d507491b17..9bcee6465ab7 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -297,7 +297,7 @@ impl GlobalState { let mut bytes = vec![]; let mut modified_rust_files = vec![]; for file in changed_files { - let vfs_path = &vfs.file_path(file.file_id); + let vfs_path = vfs.file_path(file.file_id); if let Some(path) = vfs_path.as_path() { let path = path.to_path_buf(); if reload::should_refresh_for_change(&path, file.kind()) { @@ -481,7 +481,7 @@ impl GlobalStateSnapshot { } pub(crate) fn anchored_path(&self, path: &AnchoredPathBuf) -> Url { - let mut base = self.vfs_read().file_path(path.anchor); + let mut base = self.vfs_read().file_path(path.anchor).clone(); base.pop(); let path = base.join(&path.path).unwrap(); let path = path.as_path().unwrap(); @@ -489,7 +489,7 @@ impl GlobalStateSnapshot { } pub(crate) fn file_id_to_file_path(&self, file_id: FileId) -> vfs::VfsPath { - self.vfs_read().file_path(file_id) + self.vfs_read().file_path(file_id).clone() } pub(crate) fn cargo_target_for_crate_root( @@ -497,7 +497,7 @@ impl GlobalStateSnapshot { crate_id: CrateId, ) -> Option<(&CargoWorkspace, Target)> { let file_id = self.analysis.crate_root(crate_id).ok()?; - let path = self.vfs_read().file_path(file_id); + let path = self.vfs_read().file_path(file_id).clone(); let path = path.as_path()?; self.workspaces.iter().find_map(|ws| match ws { ProjectWorkspace::Cargo { cargo, .. } => { diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index 04a043954299..0e005975fbae 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -2097,7 +2097,7 @@ pub(crate) fn fetch_dependency_list( .into_iter() .filter_map(|it| { let root_file_path = state.file_id_to_file_path(it.root_file_id); - crate_path(root_file_path).and_then(to_url).map(|path| CrateInfoResult { + crate_path(&root_file_path).and_then(to_url).map(|path| CrateInfoResult { name: it.name, version: it.version, path, @@ -2118,7 +2118,7 @@ pub(crate) fn fetch_dependency_list( /// An `Option` value representing the path to the directory of the crate with the given /// name, if such a crate is found. If no crate with the given name is found, this function /// returns `None`. -fn crate_path(root_file_path: VfsPath) -> Option { +fn crate_path(root_file_path: &VfsPath) -> Option { let mut current_dir = root_file_path.parent(); while let Some(path) = current_dir { let cargo_toml_path = path.join("../Cargo.toml")?; diff --git a/crates/vfs/src/lib.rs b/crates/vfs/src/lib.rs index 34a85818eb84..824ce3987033 100644 --- a/crates/vfs/src/lib.rs +++ b/crates/vfs/src/lib.rs @@ -163,8 +163,8 @@ impl Vfs { /// # Panics /// /// Panics if the id is not present in the `Vfs`. - pub fn file_path(&self, file_id: FileId) -> VfsPath { - self.interner.lookup(file_id).clone() + pub fn file_path(&self, file_id: FileId) -> &VfsPath { + self.interner.lookup(file_id) } /// Returns an iterator over the stored ids and their corresponding paths. From 4aab2d5cb4c3380665d27c80d2789ed0ac4e5bf6 Mon Sep 17 00:00:00 2001 From: mo8it Date: Thu, 29 Feb 2024 16:29:15 +0100 Subject: [PATCH 15/69] Remove unneeded to_owned --- crates/rust-analyzer/src/cli/analysis_stats.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index b500db77d950..f17a7eee43a9 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -369,7 +369,7 @@ impl flags::AnalysisStats { let parse = sema.parse(file_id); let file_txt = db.file_text(file_id); - let path = vfs.file_path(file_id).as_path().unwrap().to_owned(); + let path = vfs.file_path(file_id).as_path().unwrap(); for node in parse.syntax().descendants() { let expr = match syntax::ast::Expr::cast(node.clone()) { @@ -444,7 +444,7 @@ impl flags::AnalysisStats { edit.apply(&mut txt); if self.validate_term_search { - std::fs::write(&path, txt).unwrap(); + std::fs::write(path, txt).unwrap(); let res = ws.run_build_scripts(&cargo_config, &|_| ()).unwrap(); if let Some(err) = res.error() { @@ -493,7 +493,7 @@ impl flags::AnalysisStats { } // Revert file back to original state if self.validate_term_search { - std::fs::write(&path, file_txt.to_string()).unwrap(); + std::fs::write(path, file_txt.to_string()).unwrap(); } bar.inc(1); From 9df73c6cb048fc28598ad0cbfb228444a4e9a553 Mon Sep 17 00:00:00 2001 From: mo8it Date: Thu, 29 Feb 2024 16:53:48 +0100 Subject: [PATCH 16/69] Convert directly into an Arc --- crates/test-fixture/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/test-fixture/src/lib.rs b/crates/test-fixture/src/lib.rs index e118262b4edd..68324cfeab8b 100644 --- a/crates/test-fixture/src/lib.rs +++ b/crates/test-fixture/src/lib.rs @@ -149,15 +149,15 @@ impl ChangeFixture { for entry in fixture { let text = if entry.text.contains(CURSOR_MARKER) { if entry.text.contains(ESCAPED_CURSOR_MARKER) { - entry.text.replace(ESCAPED_CURSOR_MARKER, CURSOR_MARKER) + entry.text.replace(ESCAPED_CURSOR_MARKER, CURSOR_MARKER).into() } else { let (range_or_offset, text) = extract_range_or_offset(&entry.text); assert!(file_position.is_none()); file_position = Some((file_id, range_or_offset)); - text + text.into() } } else { - entry.text.clone() + entry.text.as_str().into() }; let meta = FileMeta::from_fixture(entry, current_source_root_kind); @@ -206,7 +206,7 @@ impl ChangeFixture { default_env.extend(meta.env.iter().map(|(x, y)| (x.to_owned(), y.to_owned()))); } - source_change.change_file(file_id, Some(text.into())); + source_change.change_file(file_id, Some(text)); let path = VfsPath::new_virtual_path(meta.path); file_set.insert(file_id, path); files.push(file_id); From 00a049b585554320d49e20d549530cf87df2fe02 Mon Sep 17 00:00:00 2001 From: mo8it Date: Thu, 29 Feb 2024 17:01:32 +0100 Subject: [PATCH 17/69] Avoid cloning deps --- crates/test-fixture/src/lib.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/crates/test-fixture/src/lib.rs b/crates/test-fixture/src/lib.rs index 68324cfeab8b..58a0e48bc49e 100644 --- a/crates/test-fixture/src/lib.rs +++ b/crates/test-fixture/src/lib.rs @@ -195,7 +195,10 @@ impl ChangeFixture { let prev = crates.insert(crate_name.clone(), crate_id); assert!(prev.is_none(), "multiple crates with same name: {}", crate_name); for dep in meta.deps { - let prelude = meta.extern_prelude.contains(&dep); + let prelude = match &meta.extern_prelude { + Some(v) => v.contains(&dep), + None => true, + }; let dep = CrateName::normalize_dashes(&dep); crate_deps.push((crate_name.clone(), dep, prelude)) } @@ -443,7 +446,7 @@ struct FileMeta { path: String, krate: Option<(String, CrateOrigin, Option)>, deps: Vec, - extern_prelude: Vec, + extern_prelude: Option>, cfg: CfgOptions, edition: Edition, env: Env, @@ -473,7 +476,7 @@ impl FileMeta { Self { path: f.path, krate: f.krate.map(|it| parse_crate(it, current_source_root_kind, f.library)), - extern_prelude: f.extern_prelude.unwrap_or_else(|| deps.clone()), + extern_prelude: f.extern_prelude, deps, cfg, edition: f.edition.map_or(Edition::CURRENT, |v| Edition::from_str(&v).unwrap()), From 1d28aecd13a3a19c3a9fdce81e0c50f0b74caf6b Mon Sep 17 00:00:00 2001 From: Vladislav Mamon Date: Thu, 29 Feb 2024 20:10:30 +0300 Subject: [PATCH 18/69] fix: autocomplete constants inside format strings --- .../src/completions/format_string.rs | 95 ++++++++++++++++++- 1 file changed, 93 insertions(+), 2 deletions(-) diff --git a/crates/ide-completion/src/completions/format_string.rs b/crates/ide-completion/src/completions/format_string.rs index cecbe75391d1..5512ac215346 100644 --- a/crates/ide-completion/src/completions/format_string.rs +++ b/crates/ide-completion/src/completions/format_string.rs @@ -1,6 +1,7 @@ //! Completes identifiers in format string literals. -use ide_db::syntax_helpers::format_string::is_format_string; +use hir::{ModuleDef, ScopeDef}; +use ide_db::{syntax_helpers::format_string::is_format_string, SymbolKind}; use itertools::Itertools; use syntax::{ast, AstToken, TextRange, TextSize}; @@ -33,7 +34,23 @@ pub(crate) fn format_string( ctx.locals.iter().for_each(|(name, _)| { CompletionItem::new(CompletionItemKind::Binding, source_range, name.to_smol_str()) .add_to(acc, ctx.db); - }) + }); + ctx.scope.process_all_names(&mut |name, scope| { + if let ScopeDef::ModuleDef(module_def) = scope { + let symbol_kind = match module_def { + ModuleDef::Const(..) => SymbolKind::Const, + ModuleDef::Static(..) => SymbolKind::Static, + _ => return, + }; + + CompletionItem::new( + CompletionItemKind::SymbolKind(symbol_kind), + source_range, + name.to_smol_str(), + ) + .add_to(acc, ctx.db); + } + }); } #[cfg(test)] @@ -110,6 +127,80 @@ fn main() { let foobar = 1; format_args!("{foobar"); } +"#, + ); + } + + #[test] + fn completes_constants() { + check_edit( + "FOOBAR", + r#" +//- minicore: fmt +fn main() { + const FOOBAR: usize = 42; + format_args!("{f$0"); +} +"#, + r#" +fn main() { + const FOOBAR: usize = 42; + format_args!("{FOOBAR"); +} +"#, + ); + + check_edit( + "FOOBAR", + r#" +//- minicore: fmt +fn main() { + const FOOBAR: usize = 42; + format_args!("{$0"); +} +"#, + r#" +fn main() { + const FOOBAR: usize = 42; + format_args!("{FOOBAR"); +} +"#, + ); + } + + #[test] + fn completes_static_constants() { + check_edit( + "FOOBAR", + r#" +//- minicore: fmt +fn main() { + static FOOBAR: usize = 42; + format_args!("{f$0"); +} +"#, + r#" +fn main() { + static FOOBAR: usize = 42; + format_args!("{FOOBAR"); +} +"#, + ); + + check_edit( + "FOOBAR", + r#" +//- minicore: fmt +fn main() { + static FOOBAR: usize = 42; + format_args!("{$0"); +} +"#, + r#" +fn main() { + static FOOBAR: usize = 42; + format_args!("{FOOBAR"); +} "#, ); } From dba67b46a118b6a0e58c6aa87c63f7d96a837888 Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Sat, 2 Mar 2024 10:01:04 +0800 Subject: [PATCH 19/69] update for review --- crates/hir-ty/src/display.rs | 32 +++++++++++++++++++++++++++++- crates/hir/src/display.rs | 4 ++-- crates/ide-db/src/defs.rs | 12 ++--------- crates/ide/src/hover.rs | 2 +- crates/ide/src/hover/render.rs | 10 +++++++--- crates/ide/src/hover/tests.rs | 2 +- crates/ide/src/static_index.rs | 6 +++--- crates/rust-analyzer/src/config.rs | 8 ++++---- docs/user/generated_config.adoc | 10 +++++----- editors/code/package.json | 18 ++++++++--------- 10 files changed, 65 insertions(+), 39 deletions(-) diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index f7e396de2d6b..328dea87ac11 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -62,7 +62,8 @@ pub struct HirFormatter<'a> { fmt: &'a mut dyn HirWrite, buf: String, curr_size: usize, - pub max_size: Option, + pub(crate) max_size: Option, + pub limited_size: Option, omit_verbose_types: bool, closure_style: ClosureStyle, display_target: DisplayTarget, @@ -86,6 +87,7 @@ pub trait HirDisplay { &'a self, db: &'a dyn HirDatabase, max_size: Option, + limited_size: Option, omit_verbose_types: bool, display_target: DisplayTarget, closure_style: ClosureStyle, @@ -101,6 +103,7 @@ pub trait HirDisplay { db, t: self, max_size, + limited_size, omit_verbose_types, display_target, closure_style, @@ -117,6 +120,7 @@ pub trait HirDisplay { db, t: self, max_size: None, + limited_size: None, omit_verbose_types: false, closure_style: ClosureStyle::ImplFn, display_target: DisplayTarget::Diagnostics, @@ -137,6 +141,28 @@ pub trait HirDisplay { db, t: self, max_size, + limited_size: None, + omit_verbose_types: true, + closure_style: ClosureStyle::ImplFn, + display_target: DisplayTarget::Diagnostics, + } + } + + /// Returns a `Display`able type that is human-readable and tries to limit the item inside this type. + /// Use this for showing types which may contain two many item when user hover on, like `trait`, `struct`, `enum` + fn display_limited<'a>( + &'a self, + db: &'a dyn HirDatabase, + limited_size: Option, + ) -> HirDisplayWrapper<'a, Self> + where + Self: Sized, + { + HirDisplayWrapper { + db, + t: self, + max_size: None, + limited_size, omit_verbose_types: true, closure_style: ClosureStyle::ImplFn, display_target: DisplayTarget::Diagnostics, @@ -158,6 +184,7 @@ pub trait HirDisplay { buf: String::with_capacity(20), curr_size: 0, max_size: None, + limited_size: None, omit_verbose_types: false, closure_style: ClosureStyle::ImplFn, display_target: DisplayTarget::SourceCode { module_id, allow_opaque }, @@ -178,6 +205,7 @@ pub trait HirDisplay { db, t: self, max_size: None, + limited_size: None, omit_verbose_types: false, closure_style: ClosureStyle::ImplFn, display_target: DisplayTarget::Test, @@ -295,6 +323,7 @@ pub struct HirDisplayWrapper<'a, T> { db: &'a dyn HirDatabase, t: &'a T, max_size: Option, + limited_size: Option, omit_verbose_types: bool, closure_style: ClosureStyle, display_target: DisplayTarget, @@ -323,6 +352,7 @@ impl HirDisplayWrapper<'_, T> { buf: String::with_capacity(20), curr_size: 0, max_size: self.max_size, + limited_size: self.limited_size, omit_verbose_types: self.omit_verbose_types, display_target: self.display_target, closure_style: self.closure_style, diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 08e0c6e75247..20ba72d998c3 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -598,7 +598,7 @@ impl HirDisplay for Trait { let assoc_items = self.items(f.db); let assoc_items_size = assoc_items.len(); - let max_display_size = f.max_size.unwrap_or(assoc_items_size); + let limited_size = f.limited_size.unwrap_or(assoc_items_size); if assoc_items.is_empty() { f.write_str(" {}")?; } else { @@ -617,7 +617,7 @@ impl HirDisplay for Trait { } }; f.write_str(",\n")?; - if index + 1 == max_display_size && index + 1 != assoc_items_size { + if index + 1 == limited_size && index + 1 != assoc_items_size { f.write_str(" ...\n")?; break; } diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs index 35aaf864696a..1b6ff8bad53c 100644 --- a/crates/ide-db/src/defs.rs +++ b/crates/ide-db/src/defs.rs @@ -24,12 +24,6 @@ use crate::documentation::{Documentation, HasDocs}; use crate::famous_defs::FamousDefs; use crate::RootDatabase; -#[derive(Default)] -pub struct HoverDisplayConfig { - pub trait_item_display_num: Option, - // todo: add config for struct & enum -} - // FIXME: a more precise name would probably be `Symbol`? #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] pub enum Definition { @@ -219,7 +213,7 @@ impl Definition { }) } - pub fn label(&self, db: &RootDatabase, hover_display_config: HoverDisplayConfig) -> String { + pub fn label(&self, db: &RootDatabase) -> String { match *self { Definition::Macro(it) => it.display(db).to_string(), Definition::Field(it) => it.display(db).to_string(), @@ -230,9 +224,7 @@ impl Definition { Definition::Variant(it) => it.display(db).to_string(), Definition::Const(it) => it.display(db).to_string(), Definition::Static(it) => it.display(db).to_string(), - Definition::Trait(it) => { - it.display_truncated(db, hover_display_config.trait_item_display_num).to_string() - } + Definition::Trait(it) => it.display(db).to_string(), Definition::TraitAlias(it) => it.display(db).to_string(), Definition::TypeAlias(it) => it.display(db).to_string(), Definition::BuiltinType(it) => it.name().display(db).to_string(), diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 64346a59b77f..b6877c5e8ce9 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -32,7 +32,7 @@ pub struct HoverConfig { pub documentation: bool, pub keywords: bool, pub format: HoverDocFormat, - pub trait_item_display_num: Option, + pub trait_assoc_items_size: Option, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index 6d7886feec33..f528bd512cce 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -8,7 +8,7 @@ use hir::{ }; use ide_db::{ base_db::SourceDatabase, - defs::{Definition, HoverDisplayConfig}, + defs::Definition, documentation::HasDocs, famous_defs::FamousDefs, generated::lints::{CLIPPY_LINTS, DEFAULT_LINTS, FEATURES}, @@ -406,8 +406,12 @@ pub(super) fn definition( config: &HoverConfig, ) -> Markup { let mod_path = definition_mod_path(db, &def); - let hover_config = HoverDisplayConfig { trait_item_display_num: config.trait_item_display_num }; - let label = def.label(db, hover_config); + let label = match def { + Definition::Trait(trait_) => { + trait_.display_limited(db, config.trait_assoc_items_size).to_string() + } + _ => def.label(db), + }; let docs = def.docs(db, famous_defs); let value = (|| match def { Definition::Variant(it) => { diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index e2278fe4b3ab..70f4068478d8 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -17,7 +17,7 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig { documentation: true, format: HoverDocFormat::Markdown, keywords: true, - trait_item_display_num: Some(7), + trait_assoc_items_size: None, }; fn check_hover_no_result(ra_fixture: &str) { diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index 8d6e161c1b97..0f19da0ac5fb 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -4,7 +4,7 @@ use hir::{db::HirDatabase, Crate, HirFileIdExt, Module, Semantics}; use ide_db::{ base_db::{FileId, FileRange, SourceDatabaseExt}, - defs::{Definition, HoverDisplayConfig}, + defs::Definition, documentation::Documentation, famous_defs::FamousDefs, helpers::get_definition, @@ -166,7 +166,7 @@ impl StaticIndex<'_> { documentation: true, keywords: true, format: crate::HoverDocFormat::Markdown, - trait_item_display_num: None, + trait_assoc_items_size: None, }; let tokens = tokens.filter(|token| { matches!( @@ -197,7 +197,7 @@ impl StaticIndex<'_> { enclosing_moniker: current_crate .zip(def.enclosing_definition(self.db)) .and_then(|(cc, enclosing_def)| def_to_moniker(self.db, enclosing_def, cc)), - signature: Some(def.label(self.db, HoverDisplayConfig::default())), + signature: Some(def.label(self.db)), kind: def_to_kind(self.db, def), }); self.def_map.insert(def, it); diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 40a2077cb185..259ee3ea8c20 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -368,6 +368,9 @@ config_data! { /// How to render the size information in a memory layout hover. hover_memoryLayout_size: Option = "\"both\"", + /// How many associated items of a trait to display when hovering a trait. + hover_show_traitAssocItems: Option = "null", + /// Whether to enforce the import granularity setting for all files. If set to false rust-analyzer will try to keep import styles consistent per file. imports_granularity_enforce: bool = "false", /// How imports should be grouped into use statements. @@ -590,9 +593,6 @@ config_data! { /// Show documentation. signatureInfo_documentation_enable: bool = "true", - /// How many trait item display on hover. - traitItemDisplayNum: Option = "7", - /// Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list. typing_autoClosingAngleBrackets_enable: bool = "false", @@ -1685,7 +1685,7 @@ impl Config { } }, keywords: self.data.hover_documentation_keywords_enable, - trait_item_display_num: self.data.traitItemDisplayNum, + trait_assoc_items_size: self.data.hover_show_traitAssocItems, } } diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 7d005828b8c6..7b292fc78f76 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -505,6 +505,11 @@ How to render the offset information in a memory layout hover. -- How to render the size information in a memory layout hover. -- +[[rust-analyzer.hover.show.traitAssocItems]]rust-analyzer.hover.show.traitAssocItems (default: `null`):: ++ +-- +How many associated items of a trait to display when hovering a trait. +-- [[rust-analyzer.imports.granularity.enforce]]rust-analyzer.imports.granularity.enforce (default: `false`):: + -- @@ -927,11 +932,6 @@ Show full signature of the callable. Only shows parameters if disabled. -- Show documentation. -- -[[rust-analyzer.traitItemDisplayNum]]rust-analyzer.traitItemDisplayNum (default: `7`):: -+ --- -How many trait item display on hover. --- [[rust-analyzer.typing.autoClosingAngleBrackets.enable]]rust-analyzer.typing.autoClosingAngleBrackets.enable (default: `false`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index b68ab66cdab6..719521a224ec 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -1119,6 +1119,15 @@ } ] }, + "rust-analyzer.hover.show.traitAssocItems": { + "markdownDescription": "How many associated items of a trait to display when hovering a trait.", + "default": null, + "type": [ + "null", + "integer" + ], + "minimum": 0 + }, "rust-analyzer.imports.granularity.enforce": { "markdownDescription": "Whether to enforce the import granularity setting for all files. If set to false rust-analyzer will try to keep import styles consistent per file.", "default": false, @@ -1648,15 +1657,6 @@ "default": true, "type": "boolean" }, - "rust-analyzer.traitItemDisplayNum": { - "markdownDescription": "How many trait item display on hover.", - "default": 7, - "type": [ - "null", - "integer" - ], - "minimum": 0 - }, "rust-analyzer.typing.autoClosingAngleBrackets.enable": { "markdownDescription": "Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list.", "default": false, From 7c6f7b2c49cb4f4cfbad15d0f44a2ce69918a512 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 3 Mar 2024 00:34:27 +0100 Subject: [PATCH 20/69] Update rustc_pattern_analysis --- Cargo.lock | 16 ++++++++-------- Cargo.toml | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9acace2fb331..982468765b4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1470,12 +1470,12 @@ dependencies = [ [[package]] name = "ra-ap-rustc_index" -version = "0.37.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df5a0ba0d08af366cf235dbe8eb7226cced7a4fe502c98aa434ccf416defd746" +checksum = "371db64f1be25aae96650b5528c76066ac325f0fe23efec0aab1179d75eea5c3" dependencies = [ "arrayvec", - "ra-ap-rustc_index_macros 0.37.0", + "ra-ap-rustc_index_macros 0.40.0", "smallvec", ] @@ -1493,9 +1493,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_index_macros" -version = "0.37.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1971ebf9a701e0e68387c264a32517dcb4861ad3a4862f2e2803c1121ade20d5" +checksum = "fa4a454193807f557a991f52157250fd2db95abfb96da65e85355e6949802a98" dependencies = [ "proc-macro2", "quote", @@ -1525,11 +1525,11 @@ dependencies = [ [[package]] name = "ra-ap-rustc_pattern_analysis" -version = "0.37.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c3c0e7ca9c5bdc66e3b590688e237a22ac47a48e4eac7f46b05b2abbfaf0abd" +checksum = "c9cb49490fadb58e6b8cc825f73157a33730495bfd5c6e9eef067a4b50ad1836" dependencies = [ - "ra-ap-rustc_index 0.37.0", + "ra-ap-rustc_index 0.40.0", "rustc-hash", "rustc_apfloat", "smallvec", diff --git a/Cargo.toml b/Cargo.toml index 16dd51038998..e68613c6d384 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -88,7 +88,7 @@ ra-ap-rustc_lexer = { version = "0.35.0", default-features = false } ra-ap-rustc_parse_format = { version = "0.35.0", default-features = false } ra-ap-rustc_index = { version = "0.35.0", default-features = false } ra-ap-rustc_abi = { version = "0.35.0", default-features = false } -ra-ap-rustc_pattern_analysis = { version = "0.37.0", default-features = false } +ra-ap-rustc_pattern_analysis = { version = "0.40.0", default-features = false } # local crates that aren't published to crates.io. These should not have versions. sourcegen = { path = "./crates/sourcegen" } From 4303e741de62ec9e1ebbcfbafee0ed52a92f0f2a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 4 Mar 2024 11:10:06 +0100 Subject: [PATCH 21/69] Cleanup --- Cargo.lock | 11 +- crates/base-db/Cargo.toml | 1 - crates/hir-def/src/body.rs | 4 - crates/hir-def/src/body/lower.rs | 2 - crates/hir-def/src/item_tree.rs | 49 ++- crates/hir-def/src/nameres.rs | 334 +++++++++--------- crates/hir-def/src/nameres/collector.rs | 175 ++++----- crates/hir-def/src/nameres/diagnostics.rs | 24 +- crates/hir-def/src/nameres/mod_resolution.rs | 18 +- crates/hir-def/src/nameres/path_resolution.rs | 43 ++- crates/hir-expand/Cargo.toml | 3 +- crates/hir-expand/src/builtin_attr_macro.rs | 25 +- crates/hir-expand/src/builtin_derive_macro.rs | 30 +- crates/hir-expand/src/builtin_fn_macro.rs | 54 +-- crates/hir-expand/src/change.rs | 4 +- crates/hir-expand/src/mod_path.rs | 6 + crates/hir-ty/Cargo.toml | 1 - crates/hir/Cargo.toml | 1 - crates/hir/src/lib.rs | 2 +- crates/ide-assists/Cargo.toml | 1 - crates/ide-completion/Cargo.toml | 1 - crates/ide-db/src/apply_change.rs | 4 +- crates/ide-db/src/lib.rs | 2 +- crates/ide-diagnostics/Cargo.toml | 1 - crates/ide/src/lib.rs | 6 +- crates/load-cargo/src/lib.rs | 4 +- crates/parser/Cargo.toml | 2 + crates/parser/src/lexed_str.rs | 1 + crates/parser/src/lib.rs | 1 + crates/parser/src/shortcuts.rs | 1 + crates/proc-macro-api/Cargo.toml | 1 - crates/profile/src/lib.rs | 23 -- crates/project-model/Cargo.toml | 3 +- crates/rust-analyzer/src/cli/rustc_tests.rs | 4 +- crates/rust-analyzer/src/global_state.rs | 4 +- .../src/integrated_benchmarks.rs | 14 +- crates/rust-analyzer/src/reload.rs | 6 +- crates/syntax/Cargo.toml | 1 - crates/syntax/src/lib.rs | 1 + crates/syntax/src/parsing.rs | 2 + crates/syntax/src/validation.rs | 1 + crates/test-fixture/src/lib.rs | 6 +- 42 files changed, 421 insertions(+), 456 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9acace2fb331..f074bb4e30ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,7 +71,6 @@ version = "0.0.0" dependencies = [ "cfg", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "profile", "rustc-hash", "salsa", "semver", @@ -501,7 +500,6 @@ dependencies = [ "hir-ty", "itertools", "once_cell", - "profile", "rustc-hash", "smallvec", "span", @@ -565,7 +563,6 @@ dependencies = [ "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "limit", "mbe", - "profile", "rustc-hash", "smallvec", "span", @@ -601,7 +598,6 @@ dependencies = [ "nohash-hasher", "once_cell", "oorandom", - "profile", "project-model", "ra-ap-rustc_abi", "ra-ap-rustc_index 0.35.0", @@ -673,7 +669,6 @@ dependencies = [ "hir", "ide-db", "itertools", - "profile", "smallvec", "sourcegen", "stdx", @@ -695,7 +690,6 @@ dependencies = [ "ide-db", "itertools", "once_cell", - "profile", "smallvec", "stdx", "syntax", @@ -753,7 +747,6 @@ dependencies = [ "ide-db", "itertools", "once_cell", - "profile", "serde_json", "sourcegen", "stdx", @@ -1233,6 +1226,7 @@ dependencies = [ "ra-ap-rustc_lexer", "sourcegen", "stdx", + "tracing", ] [[package]] @@ -1302,7 +1296,6 @@ dependencies = [ "memmap2", "object 0.32.0", "paths", - "profile", "rustc-hash", "serde", "serde_json", @@ -1386,7 +1379,6 @@ dependencies = [ "itertools", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "paths", - "profile", "rustc-hash", "semver", "serde", @@ -1925,7 +1917,6 @@ dependencies = [ "once_cell", "parser", "proc-macro2", - "profile", "quote", "ra-ap-rustc_lexer", "rayon", diff --git a/crates/base-db/Cargo.toml b/crates/base-db/Cargo.toml index 801ba2d1f6c8..118abf5d6eb8 100644 --- a/crates/base-db/Cargo.toml +++ b/crates/base-db/Cargo.toml @@ -21,7 +21,6 @@ tracing.workspace = true # local deps cfg.workspace = true -profile.workspace = true stdx.workspace = true syntax.workspace = true vfs.workspace = true diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs index ce8a9eab14a9..37d37fd33115 100644 --- a/crates/hir-def/src/body.rs +++ b/crates/hir-def/src/body.rs @@ -13,7 +13,6 @@ use cfg::{CfgExpr, CfgOptions}; use either::Either; use hir_expand::{name::Name, HirFileId, InFile}; use la_arena::{Arena, ArenaMap}; -use profile::Count; use rustc_hash::FxHashMap; use syntax::{ast, AstPtr, SyntaxNodePtr}; use triomphe::Arc; @@ -51,7 +50,6 @@ pub struct Body { pub body_expr: ExprId, /// Block expressions in this body that may contain inner items. block_scopes: Vec, - _c: Count, } pub type ExprPtr = AstPtr; @@ -216,7 +214,6 @@ impl Body { fn shrink_to_fit(&mut self) { let Self { - _c: _, body_expr: _, block_scopes, exprs, @@ -300,7 +297,6 @@ impl Default for Body { params: Default::default(), block_scopes: Default::default(), binding_owners: Default::default(), - _c: Default::default(), } } } diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index ad8782d3d1e3..c9300898b386 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -10,7 +10,6 @@ use hir_expand::{ ExpandError, InFile, }; use intern::Interned; -use profile::Count; use rustc_hash::FxHashMap; use smallvec::SmallVec; use span::AstIdMap; @@ -76,7 +75,6 @@ pub(super) fn lower( params: Vec::new(), body_expr: dummy_expr_id(), block_scopes: Vec::new(), - _c: Count::new(), }, expander, current_try_block_label: None, diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index c7cf611589b0..008fa7ef13af 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -50,7 +50,6 @@ use either::Either; use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile}; use intern::Interned; use la_arena::{Arena, Idx, IdxRange, RawIdx}; -use profile::Count; use rustc_hash::FxHashMap; use smallvec::SmallVec; use span::{AstIdNode, FileAstId, Span}; @@ -94,8 +93,6 @@ impl fmt::Debug for RawVisibilityId { /// The item tree of a source file. #[derive(Debug, Default, Eq, PartialEq)] pub struct ItemTree { - _c: Count, - top_level: SmallVec<[ModItem; 1]>, attrs: FxHashMap, @@ -263,14 +260,6 @@ impl ItemVisibilities { } } -static VIS_PUB: RawVisibility = RawVisibility::Public; -static VIS_PRIV_IMPLICIT: RawVisibility = - RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicitness::Implicit); -static VIS_PRIV_EXPLICIT: RawVisibility = - RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicitness::Explicit); -static VIS_PUB_CRATE: RawVisibility = - RawVisibility::Module(ModPath::from_kind(PathKind::Crate), VisibilityExplicitness::Explicit); - #[derive(Default, Debug, Eq, PartialEq)] struct ItemTreeData { uses: Arena, @@ -562,6 +551,20 @@ impl_index!(fields: Field, variants: Variant, params: Param); impl Index for ItemTree { type Output = RawVisibility; fn index(&self, index: RawVisibilityId) -> &Self::Output { + static VIS_PUB: RawVisibility = RawVisibility::Public; + static VIS_PRIV_IMPLICIT: RawVisibility = RawVisibility::Module( + ModPath::from_kind(PathKind::Super(0)), + VisibilityExplicitness::Implicit, + ); + static VIS_PRIV_EXPLICIT: RawVisibility = RawVisibility::Module( + ModPath::from_kind(PathKind::Super(0)), + VisibilityExplicitness::Explicit, + ); + static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module( + ModPath::from_kind(PathKind::Crate), + VisibilityExplicitness::Explicit, + ); + match index { RawVisibilityId::PRIV_IMPLICIT => &VIS_PRIV_IMPLICIT, RawVisibilityId::PRIV_EXPLICIT => &VIS_PRIV_EXPLICIT, @@ -871,25 +874,19 @@ impl UseTree { prefix: Option, path: &ModPath, ) -> Option<(ModPath, ImportKind)> { - match (prefix, &path.kind) { + match (prefix, path.kind) { (None, _) => Some((path.clone(), ImportKind::Plain)), (Some(mut prefix), PathKind::Plain) => { - for segment in path.segments() { - prefix.push_segment(segment.clone()); - } + prefix.extend(path.segments().iter().cloned()); Some((prefix, ImportKind::Plain)) } - (Some(mut prefix), PathKind::Super(n)) - if *n > 0 && prefix.segments().is_empty() => - { + (Some(mut prefix), PathKind::Super(n)) if n > 0 && prefix.segments().is_empty() => { // `super::super` + `super::rest` match &mut prefix.kind { PathKind::Super(m) => { cov_mark::hit!(concat_super_mod_paths); - *m += *n; - for segment in path.segments() { - prefix.push_segment(segment.clone()); - } + *m += n; + prefix.extend(path.segments().iter().cloned()); Some((prefix, ImportKind::Plain)) } _ => None, @@ -963,10 +960,10 @@ impl ModItem { | ModItem::Mod(_) | ModItem::MacroRules(_) | ModItem::Macro2(_) => None, - ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)), - ModItem::Const(konst) => Some(AssocItem::Const(*konst)), - ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)), - ModItem::Function(func) => Some(AssocItem::Function(*func)), + &ModItem::MacroCall(call) => Some(AssocItem::MacroCall(call)), + &ModItem::Const(konst) => Some(AssocItem::Const(konst)), + &ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(alias)), + &ModItem::Function(func) => Some(AssocItem::Function(func)), } } diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index 270468ad0a62..764617eafb7b 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -65,7 +65,6 @@ use hir_expand::{ }; use itertools::Itertools; use la_arena::Arena; -use profile::Count; use rustc_hash::{FxHashMap, FxHashSet}; use span::FileAstId; use stdx::format_to; @@ -95,7 +94,6 @@ use crate::{ /// is computed by the `block_def_map` query. #[derive(Debug, PartialEq, Eq)] pub struct DefMap { - _c: Count, /// When this is a block def map, this will hold the block id of the block and module that /// contains this block. block: Option, @@ -154,6 +152,23 @@ struct DefMapCrateData { } impl DefMapCrateData { + fn new(edition: Edition) -> Self { + Self { + extern_prelude: FxHashMap::default(), + exported_derives: FxHashMap::default(), + fn_proc_macro_mapping: FxHashMap::default(), + proc_macro_loading_error: None, + registered_attrs: Vec::new(), + registered_tools: Vec::new(), + unstable_features: FxHashSet::default(), + rustc_coherence_is_core: false, + no_core: false, + no_std: false, + edition, + recursion_limit: None, + } + } + fn shrink_to_fit(&mut self) { let Self { extern_prelude, @@ -305,67 +320,67 @@ impl DefMap { /// The module id of a crate or block root. pub const ROOT: LocalModuleId = LocalModuleId::from_raw(la_arena::RawIdx::from_u32(0)); - pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc { + pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, crate_id: CrateId) -> Arc { let crate_graph = db.crate_graph(); - let krate_name = crate_graph[krate].display_name.as_deref().unwrap_or_default(); - - let _p = tracing::span!(tracing::Level::INFO, "crate_def_map_query", ?krate_name).entered(); + let krate = &crate_graph[crate_id]; + let name = krate.display_name.as_deref().unwrap_or_default(); + let _p = tracing::span!(tracing::Level::INFO, "crate_def_map_query", ?name).entered(); - let crate_graph = db.crate_graph(); + let module_data = ModuleData::new( + ModuleOrigin::CrateRoot { definition: krate.root_file_id }, + Visibility::Public, + ); - let edition = crate_graph[krate].edition; - let origin = ModuleOrigin::CrateRoot { definition: crate_graph[krate].root_file_id }; - let def_map = DefMap::empty(krate, edition, ModuleData::new(origin, Visibility::Public)); - let def_map = collector::collect_defs( - db, - def_map, - TreeId::new(crate_graph[krate].root_file_id.into(), None), + let def_map = DefMap::empty( + crate_id, + Arc::new(DefMapCrateData::new(krate.edition)), + module_data, + None, ); + let def_map = + collector::collect_defs(db, def_map, TreeId::new(krate.root_file_id.into(), None)); Arc::new(def_map) } pub(crate) fn block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc { - let block: BlockLoc = block_id.lookup(db); - - let parent_map = block.module.def_map(db); - let krate = block.module.krate; - let local_id = LocalModuleId::from_raw(la_arena::RawIdx::from(0)); - // NB: we use `None` as block here, which would be wrong for implicit - // modules declared by blocks with items. At the moment, we don't use - // this visibility for anything outside IDE, so that's probably OK. + let BlockLoc { ast_id, module } = block_id.lookup(db); + let visibility = Visibility::Module( - ModuleId { krate, local_id, block: None }, + ModuleId { krate: module.krate, local_id: Self::ROOT, block: module.block }, VisibilityExplicitness::Implicit, ); - let module_data = ModuleData::new( - ModuleOrigin::BlockExpr { block: block.ast_id, id: block_id }, - visibility, + let module_data = + ModuleData::new(ModuleOrigin::BlockExpr { block: ast_id, id: block_id }, visibility); + + let parent_map = module.def_map(db); + let def_map = DefMap::empty( + module.krate, + parent_map.data.clone(), + module_data, + Some(BlockInfo { + block: block_id, + parent: BlockRelativeModuleId { block: module.block, local_id: module.local_id }, + }), ); - let mut def_map = DefMap::empty(krate, parent_map.data.edition, module_data); - def_map.data = parent_map.data.clone(); - def_map.block = Some(BlockInfo { - block: block_id, - parent: BlockRelativeModuleId { - block: block.module.block, - local_id: block.module.local_id, - }, - }); - let def_map = - collector::collect_defs(db, def_map, TreeId::new(block.ast_id.file_id, Some(block_id))); + collector::collect_defs(db, def_map, TreeId::new(ast_id.file_id, Some(block_id))); Arc::new(def_map) } - fn empty(krate: CrateId, edition: Edition, module_data: ModuleData) -> DefMap { + fn empty( + krate: CrateId, + crate_data: Arc, + module_data: ModuleData, + block: Option, + ) -> DefMap { let mut modules: Arena = Arena::default(); let root = modules.alloc(module_data); assert_eq!(root, Self::ROOT); DefMap { - _c: Count::new(), - block: None, + block, modules, krate, prelude: None, @@ -373,23 +388,36 @@ impl DefMap { derive_helpers_in_scope: FxHashMap::default(), diagnostics: Vec::new(), enum_definitions: FxHashMap::default(), - data: Arc::new(DefMapCrateData { - extern_prelude: FxHashMap::default(), - exported_derives: FxHashMap::default(), - fn_proc_macro_mapping: FxHashMap::default(), - proc_macro_loading_error: None, - registered_attrs: Vec::new(), - registered_tools: Vec::new(), - unstable_features: FxHashSet::default(), - rustc_coherence_is_core: false, - no_core: false, - no_std: false, - edition, - recursion_limit: None, - }), + data: crate_data, + } + } + fn shrink_to_fit(&mut self) { + // Exhaustive match to require handling new fields. + let Self { + macro_use_prelude, + diagnostics, + modules, + derive_helpers_in_scope, + block: _, + krate: _, + prelude: _, + data: _, + enum_definitions, + } = self; + + macro_use_prelude.shrink_to_fit(); + diagnostics.shrink_to_fit(); + modules.shrink_to_fit(); + derive_helpers_in_scope.shrink_to_fit(); + enum_definitions.shrink_to_fit(); + for (_, module) in modules.iter_mut() { + module.children.shrink_to_fit(); + module.scope.shrink_to_fit(); } } +} +impl DefMap { pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator + '_ { self.modules .iter() @@ -440,26 +468,6 @@ impl DefMap { self.krate } - pub(crate) fn block_id(&self) -> Option { - self.block.map(|block| block.block) - } - - pub(crate) fn prelude(&self) -> Option<(ModuleId, Option)> { - self.prelude - } - - pub(crate) fn extern_prelude( - &self, - ) -> impl Iterator))> + '_ { - self.data.extern_prelude.iter().map(|(name, &def)| (name, def)) - } - - pub(crate) fn macro_use_prelude( - &self, - ) -> impl Iterator))> + '_ { - self.macro_use_prelude.iter().map(|(name, &def)| (name, def)) - } - pub fn module_id(&self, local_id: LocalModuleId) -> ModuleId { let block = self.block.map(|b| b.block); ModuleId { krate: self.krate, local_id, block } @@ -475,68 +483,6 @@ impl DefMap { self.module_id(Self::ROOT) } - pub(crate) fn resolve_path( - &self, - db: &dyn DefDatabase, - original_module: LocalModuleId, - path: &ModPath, - shadow: BuiltinShadowMode, - expected_macro_subns: Option, - ) -> (PerNs, Option) { - let res = self.resolve_path_fp_with_macro( - db, - ResolveMode::Other, - original_module, - path, - shadow, - expected_macro_subns, - ); - (res.resolved_def, res.segment_index) - } - - pub(crate) fn resolve_path_locally( - &self, - db: &dyn DefDatabase, - original_module: LocalModuleId, - path: &ModPath, - shadow: BuiltinShadowMode, - ) -> (PerNs, Option) { - let res = self.resolve_path_fp_with_macro_single( - db, - ResolveMode::Other, - original_module, - path, - shadow, - None, // Currently this function isn't used for macro resolution. - ); - (res.resolved_def, res.segment_index) - } - - /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module. - /// - /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns - /// `None`, iteration continues. - pub(crate) fn with_ancestor_maps( - &self, - db: &dyn DefDatabase, - local_mod: LocalModuleId, - f: &mut dyn FnMut(&DefMap, LocalModuleId) -> Option, - ) -> Option { - if let Some(it) = f(self, local_mod) { - return Some(it); - } - let mut block = self.block; - while let Some(block_info) = block { - let parent = block_info.parent.def_map(db, self.krate); - if let Some(it) = f(&parent, block_info.parent.local_id) { - return Some(it); - } - block = parent.block; - } - - None - } - /// If this `DefMap` is for a block expression, returns the module containing the block (which /// might again be a block, or a module inside a block). pub fn parent(&self) -> Option { @@ -559,6 +505,16 @@ impl DefMap { } } + /// Get a reference to the def map's diagnostics. + pub fn diagnostics(&self) -> &[DefDiagnostic] { + self.diagnostics.as_slice() + } + + pub fn recursion_limit(&self) -> u32 { + // 128 is the default in rustc + self.data.recursion_limit.unwrap_or(128) + } + // FIXME: this can use some more human-readable format (ideally, an IR // even), as this should be a great debugging aid. pub fn dump(&self, db: &dyn DefDatabase) -> String { @@ -608,41 +564,89 @@ impl DefMap { format_to!(buf, "crate scope\n"); buf } +} - fn shrink_to_fit(&mut self) { - // Exhaustive match to require handling new fields. - let Self { - _c: _, - macro_use_prelude, - diagnostics, - modules, - derive_helpers_in_scope, - block: _, - krate: _, - prelude: _, - data: _, - enum_definitions, - } = self; +impl DefMap { + pub(crate) fn block_id(&self) -> Option { + self.block.map(|block| block.block) + } - macro_use_prelude.shrink_to_fit(); - diagnostics.shrink_to_fit(); - modules.shrink_to_fit(); - derive_helpers_in_scope.shrink_to_fit(); - enum_definitions.shrink_to_fit(); - for (_, module) in modules.iter_mut() { - module.children.shrink_to_fit(); - module.scope.shrink_to_fit(); - } + pub(crate) fn prelude(&self) -> Option<(ModuleId, Option)> { + self.prelude } - /// Get a reference to the def map's diagnostics. - pub fn diagnostics(&self) -> &[DefDiagnostic] { - self.diagnostics.as_slice() + pub(crate) fn extern_prelude( + &self, + ) -> impl Iterator))> + '_ { + self.data.extern_prelude.iter().map(|(name, &def)| (name, def)) } - pub fn recursion_limit(&self) -> u32 { - // 128 is the default in rustc - self.data.recursion_limit.unwrap_or(128) + pub(crate) fn macro_use_prelude( + &self, + ) -> impl Iterator))> + '_ { + self.macro_use_prelude.iter().map(|(name, &def)| (name, def)) + } + + pub(crate) fn resolve_path( + &self, + db: &dyn DefDatabase, + original_module: LocalModuleId, + path: &ModPath, + shadow: BuiltinShadowMode, + expected_macro_subns: Option, + ) -> (PerNs, Option) { + let res = self.resolve_path_fp_with_macro( + db, + ResolveMode::Other, + original_module, + path, + shadow, + expected_macro_subns, + ); + (res.resolved_def, res.segment_index) + } + + pub(crate) fn resolve_path_locally( + &self, + db: &dyn DefDatabase, + original_module: LocalModuleId, + path: &ModPath, + shadow: BuiltinShadowMode, + ) -> (PerNs, Option) { + let res = self.resolve_path_fp_with_macro_single( + db, + ResolveMode::Other, + original_module, + path, + shadow, + None, // Currently this function isn't used for macro resolution. + ); + (res.resolved_def, res.segment_index) + } + + /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module. + /// + /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns + /// `None`, iteration continues. + pub(crate) fn with_ancestor_maps( + &self, + db: &dyn DefDatabase, + local_mod: LocalModuleId, + f: &mut dyn FnMut(&DefMap, LocalModuleId) -> Option, + ) -> Option { + if let Some(it) = f(self, local_mod) { + return Some(it); + } + let mut block = self.block; + while let Some(block_info) = block { + let parent = block_info.parent.def_map(db, self.krate); + if let Some(it) = f(&parent, block_info.parent.local_id) { + return Some(it); + } + block = parent.block; + } + + None } } diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 538e735688ba..18aefbf332c8 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -64,19 +64,18 @@ static FIXED_POINT_LIMIT: Limit = Limit::new(8192); pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeId) -> DefMap { let crate_graph = db.crate_graph(); - let mut deps = FxHashMap::default(); - // populate external prelude and dependency list let krate = &crate_graph[def_map.krate]; + + // populate external prelude and dependency list + let mut deps = + FxHashMap::with_capacity_and_hasher(krate.dependencies.len(), Default::default()); for dep in &krate.dependencies { tracing::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id); deps.insert(dep.as_name(), dep.clone()); } - let cfg_options = &krate.cfg_options; - - let is_proc_macro = krate.is_proc_macro; - let proc_macros = if is_proc_macro { + let proc_macros = if krate.is_proc_macro { match db.proc_macros().get(&def_map.krate) { Some(Ok(proc_macros)) => { Ok(proc_macros @@ -124,11 +123,11 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI indeterminate_imports: Vec::new(), unresolved_macros: Vec::new(), mod_dirs: FxHashMap::default(), - cfg_options, + cfg_options: &krate.cfg_options, proc_macros, from_glob_import: Default::default(), skip_attrs: Default::default(), - is_proc_macro, + is_proc_macro: krate.is_proc_macro, }; if tree_id.is_block() { collector.seed_with_inner(tree_id); @@ -302,71 +301,50 @@ impl DefCollector<'_> { return; } } - let attr_name = match attr.path.as_ident() { - Some(name) => name, - None => continue, - }; + let Some(attr_name) = attr.path.as_ident() else { continue }; - if *attr_name == hir_expand::name![recursion_limit] { - if let Some(limit) = attr.string_value() { - if let Ok(limit) = limit.parse() { - crate_data.recursion_limit = Some(limit); + match () { + () if *attr_name == hir_expand::name![recursion_limit] => { + if let Some(limit) = attr.string_value() { + if let Ok(limit) = limit.parse() { + crate_data.recursion_limit = Some(limit); + } } } - continue; - } - - if *attr_name == hir_expand::name![crate_type] { - if let Some("proc-macro") = attr.string_value().map(SmolStr::as_str) { - self.is_proc_macro = true; + () if *attr_name == hir_expand::name![crate_type] => { + if let Some("proc-macro") = attr.string_value().map(SmolStr::as_str) { + self.is_proc_macro = true; + } } - continue; - } - - if *attr_name == hir_expand::name![no_core] { - crate_data.no_core = true; - continue; - } - - if *attr_name == hir_expand::name![no_std] { - crate_data.no_std = true; - continue; - } - - if attr_name.as_text().as_deref() == Some("rustc_coherence_is_core") { - crate_data.rustc_coherence_is_core = true; - continue; - } - - if *attr_name == hir_expand::name![feature] { - let features = attr - .parse_path_comma_token_tree(self.db.upcast()) - .into_iter() - .flatten() - .filter_map(|(feat, _)| match feat.segments() { - [name] => Some(name.to_smol_str()), - _ => None, - }); - crate_data.unstable_features.extend(features); - } - - let attr_is_register_like = *attr_name == hir_expand::name![register_attr] - || *attr_name == hir_expand::name![register_tool]; - if !attr_is_register_like { - continue; - } - - let registered_name = match attr.single_ident_value() { - Some(ident) => ident.as_name(), - _ => continue, - }; - - if *attr_name == hir_expand::name![register_attr] { - crate_data.registered_attrs.push(registered_name.to_smol_str()); - cov_mark::hit!(register_attr); - } else { - crate_data.registered_tools.push(registered_name.to_smol_str()); - cov_mark::hit!(register_tool); + () if *attr_name == hir_expand::name![no_core] => crate_data.no_core = true, + () if *attr_name == hir_expand::name![no_std] => crate_data.no_std = true, + () if attr_name.as_text().as_deref() == Some("rustc_coherence_is_core") => { + crate_data.rustc_coherence_is_core = true; + } + () if *attr_name == hir_expand::name![feature] => { + let features = attr + .parse_path_comma_token_tree(self.db.upcast()) + .into_iter() + .flatten() + .filter_map(|(feat, _)| match feat.segments() { + [name] => Some(name.to_smol_str()), + _ => None, + }); + crate_data.unstable_features.extend(features); + } + () if *attr_name == hir_expand::name![register_attr] => { + if let Some(ident) = attr.single_ident_value() { + crate_data.registered_attrs.push(ident.text.clone()); + cov_mark::hit!(register_attr); + } + } + () if *attr_name == hir_expand::name![register_tool] => { + if let Some(ident) = attr.single_ident_value() { + crate_data.registered_tools.push(ident.text.clone()); + cov_mark::hit!(register_tool); + } + } + () => (), } } @@ -409,6 +387,7 @@ impl DefCollector<'_> { // main name resolution fixed-point loop. let mut i = 0; 'resolve_attr: loop { + let _p = tracing::span!(tracing::Level::INFO, "resolve_macros loop").entered(); 'resolve_macros: loop { self.db.unwind_if_cancelled(); @@ -466,9 +445,8 @@ impl DefCollector<'_> { // Additionally, while the proc macro entry points must be `pub`, they are not publicly // exported in type/value namespace. This function reduces the visibility of all items // in the crate root that aren't proc macros. - let root = DefMap::ROOT; - let module_id = self.def_map.module_id(root); - let root = &mut self.def_map.modules[root]; + let module_id = self.def_map.module_id(DefMap::ROOT); + let root = &mut self.def_map.modules[DefMap::ROOT]; root.scope.censor_non_proc_macros(module_id); } } @@ -828,12 +806,10 @@ impl DefCollector<'_> { return PartialResolvedImport::Unresolved; } - if let Some(krate) = res.krate { - if krate != self.def_map.krate { - return PartialResolvedImport::Resolved( - def.filter_visibility(|v| matches!(v, Visibility::Public)), - ); - } + if res.from_differing_crate { + return PartialResolvedImport::Resolved( + def.filter_visibility(|v| matches!(v, Visibility::Public)), + ); } // Check whether all namespaces are resolved. @@ -1920,7 +1896,7 @@ impl ModCollector<'_, '_> { } fn collect_module(&mut self, module_id: FileItemTreeId, attrs: &Attrs) { - let path_attr = attrs.by_key("path").string_value(); + let path_attr = attrs.by_key("path").string_value().map(SmolStr::as_str); let is_macro_use = attrs.by_key("macro_use").exists(); let module = &self.item_tree[module_id]; match &module.kind { @@ -1934,25 +1910,26 @@ impl ModCollector<'_, '_> { module_id, ); - if let Some(mod_dir) = self.mod_dir.descend_into_definition(&module.name, path_attr) - { - ModCollector { - def_collector: &mut *self.def_collector, - macro_depth: self.macro_depth, - module_id, - tree_id: self.tree_id, - item_tree: self.item_tree, - mod_dir, - } - .collect_in_top_module(items); - if is_macro_use { - self.import_all_legacy_macros(module_id); - } + let Some(mod_dir) = self.mod_dir.descend_into_definition(&module.name, path_attr) + else { + return; + }; + ModCollector { + def_collector: &mut *self.def_collector, + macro_depth: self.macro_depth, + module_id, + tree_id: self.tree_id, + item_tree: self.item_tree, + mod_dir, + } + .collect_in_top_module(items); + if is_macro_use { + self.import_all_legacy_macros(module_id); } } // out of line module, resolve, parse and recurse ModKind::Outline => { - let ast_id = AstId::new(self.tree_id.file_id(), module.ast_id); + let ast_id = AstId::new(self.file_id(), module.ast_id); let db = self.def_collector.db; match self.mod_dir.resolve_declaration(db, self.file_id(), &module.name, path_attr) { @@ -2445,7 +2422,7 @@ mod tests { use base_db::SourceDatabase; use test_fixture::WithFixture; - use crate::test_db::TestDB; + use crate::{nameres::DefMapCrateData, test_db::TestDB}; use super::*; @@ -2476,8 +2453,12 @@ mod tests { let edition = db.crate_graph()[krate].edition; let module_origin = ModuleOrigin::CrateRoot { definition: file_id }; - let def_map = - DefMap::empty(krate, edition, ModuleData::new(module_origin, Visibility::Public)); + let def_map = DefMap::empty( + krate, + Arc::new(DefMapCrateData::new(edition)), + ModuleData::new(module_origin, Visibility::Public), + None, + ); do_collect_defs(&db, def_map) } diff --git a/crates/hir-def/src/nameres/diagnostics.rs b/crates/hir-def/src/nameres/diagnostics.rs index 161b2c059909..b5a302dbcaf6 100644 --- a/crates/hir-def/src/nameres/diagnostics.rs +++ b/crates/hir-def/src/nameres/diagnostics.rs @@ -1,5 +1,7 @@ //! Diagnostics emitted during DefMap construction. +use std::ops::Not; + use base_db::CrateId; use cfg::{CfgExpr, CfgOptions}; use hir_expand::{attrs::AttrId, ErasedAstId, MacroCallKind}; @@ -16,27 +18,16 @@ use crate::{ #[derive(Debug, PartialEq, Eq)] pub enum DefDiagnosticKind { UnresolvedModule { ast: AstId, candidates: Box<[String]> }, - UnresolvedExternCrate { ast: AstId }, - UnresolvedImport { id: ItemTreeId, index: Idx }, - UnconfiguredCode { ast: ErasedAstId, cfg: CfgExpr, opts: CfgOptions }, - UnresolvedProcMacro { ast: MacroCallKind, krate: CrateId }, - UnresolvedMacroCall { ast: MacroCallKind, path: ModPath }, - MacroError { ast: MacroCallKind, message: String }, - MacroExpansionParseError { ast: MacroCallKind, errors: Box<[SyntaxError]> }, - UnimplementedBuiltinMacro { ast: AstId }, - InvalidDeriveTarget { ast: AstId, id: usize }, - MalformedDerive { ast: AstId, id: usize }, - MacroDefError { ast: AstId, message: String }, } @@ -45,11 +36,12 @@ pub struct DefDiagnostics(Option>>); impl DefDiagnostics { pub fn new(diagnostics: Vec) -> Self { - Self(if diagnostics.is_empty() { - None - } else { - Some(triomphe::Arc::new(diagnostics.into_boxed_slice())) - }) + Self( + diagnostics + .is_empty() + .not() + .then(|| triomphe::Arc::new(diagnostics.into_boxed_slice())), + ) } pub fn iter(&self) -> impl Iterator { diff --git a/crates/hir-def/src/nameres/mod_resolution.rs b/crates/hir-def/src/nameres/mod_resolution.rs index c45200e2de9d..696fb6a961cd 100644 --- a/crates/hir-def/src/nameres/mod_resolution.rs +++ b/crates/hir-def/src/nameres/mod_resolution.rs @@ -3,7 +3,6 @@ use arrayvec::ArrayVec; use base_db::{AnchoredPath, FileId}; use hir_expand::{name::Name, HirFileIdExt, MacroFileIdExt}; use limit::Limit; -use syntax::SmolStr; use crate::{db::DefDatabase, HirFileId}; @@ -29,9 +28,9 @@ impl ModDir { pub(super) fn descend_into_definition( &self, name: &Name, - attr_path: Option<&SmolStr>, + attr_path: Option<&str>, ) -> Option { - let path = match attr_path.map(SmolStr::as_str) { + let path = match attr_path { None => { let mut path = self.dir_path.clone(); path.push(&name.unescaped().to_smol_str()); @@ -63,10 +62,9 @@ impl ModDir { db: &dyn DefDatabase, file_id: HirFileId, name: &Name, - attr_path: Option<&SmolStr>, + attr_path: Option<&str>, ) -> Result<(FileId, bool, ModDir), Box<[String]>> { let name = name.unescaped(); - let orig_file_id = file_id.original_file_respecting_includes(db.upcast()); let mut candidate_files = ArrayVec::<_, 2>::new(); match attr_path { @@ -91,17 +89,19 @@ impl ModDir { } }; + let orig_file_id = file_id.original_file_respecting_includes(db.upcast()); for candidate in candidate_files.iter() { let path = AnchoredPath { anchor: orig_file_id, path: candidate.as_str() }; if let Some(file_id) = db.resolve_path(path) { let is_mod_rs = candidate.ends_with("/mod.rs"); - let (dir_path, root_non_dir_owner) = if is_mod_rs || attr_path.is_some() { - (DirPath::empty(), false) + let root_dir_owner = is_mod_rs || attr_path.is_some(); + let dir_path = if root_dir_owner { + DirPath::empty() } else { - (DirPath::new(format!("{}/", name.display(db.upcast()))), true) + DirPath::new(format!("{}/", name.display(db.upcast()))) }; - if let Some(mod_dir) = self.child(dir_path, root_non_dir_owner) { + if let Some(mod_dir) = self.child(dir_path, !root_dir_owner) { return Ok((file_id, is_mod_rs, mod_dir)); } } diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs index 1e13f7f8fd01..9e53b0372830 100644 --- a/crates/hir-def/src/nameres/path_resolution.rs +++ b/crates/hir-def/src/nameres/path_resolution.rs @@ -22,7 +22,7 @@ use crate::{ path::{ModPath, PathKind}, per_ns::PerNs, visibility::{RawVisibility, Visibility}, - AdtId, CrateId, LocalModuleId, ModuleDefId, + AdtId, LocalModuleId, ModuleDefId, }; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -42,21 +42,21 @@ pub(super) struct ResolvePathResult { pub(super) resolved_def: PerNs, pub(super) segment_index: Option, pub(super) reached_fixedpoint: ReachedFixedPoint, - pub(super) krate: Option, + pub(super) from_differing_crate: bool, } impl ResolvePathResult { fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult { - ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None, None) + ResolvePathResult::new(PerNs::none(), reached_fixedpoint, None, false) } - fn with( + fn new( resolved_def: PerNs, reached_fixedpoint: ReachedFixedPoint, segment_index: Option, - krate: Option, + from_differing_crate: bool, ) -> ResolvePathResult { - ResolvePathResult { resolved_def, segment_index, reached_fixedpoint, krate } + ResolvePathResult { resolved_def, segment_index, reached_fixedpoint, from_differing_crate } } } @@ -134,7 +134,19 @@ impl DefMap { // resolving them to. Pass `None` otherwise, e.g. when we're resolving import paths. expected_macro_subns: Option, ) -> ResolvePathResult { - let mut result = ResolvePathResult::empty(ReachedFixedPoint::No); + let mut result = self.resolve_path_fp_with_macro_single( + db, + mode, + original_module, + path, + shadow, + expected_macro_subns, + ); + + if self.block.is_none() { + // If we're in the root `DefMap`, we can resolve the path directly. + return result; + } let mut arc; let mut current_map = self; @@ -153,8 +165,7 @@ impl DefMap { if result.reached_fixedpoint == ReachedFixedPoint::No { result.reached_fixedpoint = new.reached_fixedpoint; } - // FIXME: this doesn't seem right; what if the different namespace resolutions come from different crates? - result.krate = result.krate.or(new.krate); + result.from_differing_crate |= new.from_differing_crate; result.segment_index = match (result.segment_index, new.segment_index) { (Some(idx), None) => Some(idx), (Some(old), Some(new)) => Some(old.max(new)), @@ -333,11 +344,11 @@ impl DefMap { // expectation is discarded. let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow, None); - return ResolvePathResult::with( + return ResolvePathResult::new( def, ReachedFixedPoint::Yes, s.map(|s| s + i), - Some(module.krate), + true, ); } @@ -385,11 +396,11 @@ impl DefMap { match res { Some(res) => res, None => { - return ResolvePathResult::with( + return ResolvePathResult::new( PerNs::types(e.into(), vis, imp), ReachedFixedPoint::Yes, Some(i), - Some(self.krate), + false, ) } } @@ -403,11 +414,11 @@ impl DefMap { curr, ); - return ResolvePathResult::with( + return ResolvePathResult::new( PerNs::types(s, vis, imp), ReachedFixedPoint::Yes, Some(i), - Some(self.krate), + false, ); } }; @@ -416,7 +427,7 @@ impl DefMap { .filter_visibility(|vis| vis.is_visible_from_def_map(db, self, original_module)); } - ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None, Some(self.krate)) + ResolvePathResult::new(curr_per_ns, ReachedFixedPoint::Yes, None, false) } fn resolve_name_in_module( diff --git a/crates/hir-expand/Cargo.toml b/crates/hir-expand/Cargo.toml index 506a188a211d..4f3080801565 100644 --- a/crates/hir-expand/Cargo.toml +++ b/crates/hir-expand/Cargo.toml @@ -28,7 +28,6 @@ intern.workspace = true base-db.workspace = true cfg.workspace = true syntax.workspace = true -profile.workspace = true tt.workspace = true mbe.workspace = true limit.workspace = true @@ -38,4 +37,4 @@ span.workspace = true expect-test = "1.4.0" [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/hir-expand/src/builtin_attr_macro.rs b/crates/hir-expand/src/builtin_attr_macro.rs index 903b0d480700..a0102f36aff5 100644 --- a/crates/hir-expand/src/builtin_attr_macro.rs +++ b/crates/hir-expand/src/builtin_attr_macro.rs @@ -4,23 +4,17 @@ use span::{MacroCallId, Span}; use crate::{db::ExpandDatabase, name, tt, ExpandResult, MacroCallKind}; macro_rules! register_builtin { - ($expand_fn:ident: $(($name:ident, $variant:ident) => $expand:ident),* ) => { + ($(($name:ident, $variant:ident) => $expand:ident),* ) => { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum BuiltinAttrExpander { $($variant),* } impl BuiltinAttrExpander { - pub fn $expand_fn( - &self, - db: &dyn ExpandDatabase, - id: MacroCallId, - tt: &tt::Subtree, - ) -> ExpandResult { - let expander = match *self { + pub fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree) -> ExpandResult { + match *self { $( BuiltinAttrExpander::$variant => $expand, )* - }; - expander(db, id, tt) + } } fn find_by_name(name: &name::Name) -> Option { @@ -35,6 +29,15 @@ macro_rules! register_builtin { } impl BuiltinAttrExpander { + pub fn expand( + &self, + db: &dyn ExpandDatabase, + id: MacroCallId, + tt: &tt::Subtree, + ) -> ExpandResult { + self.expander()(db, id, tt) + } + pub fn is_derive(self) -> bool { matches!(self, BuiltinAttrExpander::Derive | BuiltinAttrExpander::DeriveConst) } @@ -46,7 +49,7 @@ impl BuiltinAttrExpander { } } -register_builtin! { expand: +register_builtin! { (bench, Bench) => dummy_attr_expand, (cfg, Cfg) => dummy_attr_expand, (cfg_attr, CfgAttr) => dummy_attr_expand, diff --git a/crates/hir-expand/src/builtin_derive_macro.rs b/crates/hir-expand/src/builtin_derive_macro.rs index 279548751434..f36f48baaee1 100644 --- a/crates/hir-expand/src/builtin_derive_macro.rs +++ b/crates/hir-expand/src/builtin_derive_macro.rs @@ -25,20 +25,10 @@ macro_rules! register_builtin { } impl BuiltinDeriveExpander { - pub fn expand( - &self, - db: &dyn ExpandDatabase, - id: MacroCallId, - tt: &ast::Adt, - token_map: SpanMapRef<'_>, - ) -> ExpandResult { - let expander = match *self { + pub fn expander(&self) -> fn(Span, &ast::Adt, SpanMapRef<'_>) -> ExpandResult { + match *self { $( BuiltinDeriveExpander::$trait => $expand, )* - }; - - let span = db.lookup_intern_macro_call(id).call_site; - let span = span_with_def_site_ctxt(db, span, id); - expander(span, tt, token_map) + } } fn find_by_name(name: &name::Name) -> Option { @@ -52,6 +42,20 @@ macro_rules! register_builtin { }; } +impl BuiltinDeriveExpander { + pub fn expand( + &self, + db: &dyn ExpandDatabase, + id: MacroCallId, + tt: &ast::Adt, + token_map: SpanMapRef<'_>, + ) -> ExpandResult { + let span = db.lookup_intern_macro_call(id).call_site; + let span = span_with_def_site_ctxt(db, span, id); + self.expander()(span, tt, token_map) + } +} + register_builtin! { Copy => copy_expand, Clone => clone_expand, diff --git a/crates/hir-expand/src/builtin_fn_macro.rs b/crates/hir-expand/src/builtin_fn_macro.rs index 90cd3af75783..0fd0c25dcce2 100644 --- a/crates/hir-expand/src/builtin_fn_macro.rs +++ b/crates/hir-expand/src/builtin_fn_macro.rs @@ -31,36 +31,18 @@ macro_rules! register_builtin { } impl BuiltinFnLikeExpander { - pub fn expand( - &self, - db: &dyn ExpandDatabase, - id: MacroCallId, - tt: &tt::Subtree, - ) -> ExpandResult { - let expander = match *self { + pub fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree, Span) -> ExpandResult { + match *self { $( BuiltinFnLikeExpander::$kind => $expand, )* - }; - - let span = db.lookup_intern_macro_call(id).call_site; - let span = span_with_def_site_ctxt(db, span, id); - expander(db, id, tt, span) + } } } impl EagerExpander { - pub fn expand( - &self, - db: &dyn ExpandDatabase, - id: MacroCallId, - tt: &tt::Subtree, - ) -> ExpandResult { - let expander = match *self { + pub fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree, Span) -> ExpandResult { + match *self { $( EagerExpander::$e_kind => $e_expand, )* - }; - - let span = db.lookup_intern_macro_call(id).call_site; - let span = span_with_def_site_ctxt(db, span, id); - expander(db, id, tt, span) + } } } @@ -74,7 +56,31 @@ macro_rules! register_builtin { }; } +impl BuiltinFnLikeExpander { + pub fn expand( + &self, + db: &dyn ExpandDatabase, + id: MacroCallId, + tt: &tt::Subtree, + ) -> ExpandResult { + let span = db.lookup_intern_macro_call(id).call_site; + let span = span_with_def_site_ctxt(db, span, id); + self.expander()(db, id, tt, span) + } +} + impl EagerExpander { + pub fn expand( + &self, + db: &dyn ExpandDatabase, + id: MacroCallId, + tt: &tt::Subtree, + ) -> ExpandResult { + let span = db.lookup_intern_macro_call(id).call_site; + let span = span_with_def_site_ctxt(db, span, id); + self.expander()(db, id, tt, span) + } + pub fn is_include(&self) -> bool { matches!(self, EagerExpander::Include) } diff --git a/crates/hir-expand/src/change.rs b/crates/hir-expand/src/change.rs index c6611438e64d..8b9e5a59df8f 100644 --- a/crates/hir-expand/src/change.rs +++ b/crates/hir-expand/src/change.rs @@ -11,14 +11,14 @@ use triomphe::Arc; use crate::{db::ExpandDatabase, proc_macro::ProcMacros}; #[derive(Debug, Default)] -pub struct Change { +pub struct ChangeWithProcMacros { pub source_change: FileChange, pub proc_macros: Option, pub toolchains: Option>>, pub target_data_layouts: Option>, } -impl Change { +impl ChangeWithProcMacros { pub fn new() -> Self { Self::default() } diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs index 0cf1fadec972..ae10ad2f8019 100644 --- a/crates/hir-expand/src/mod_path.rs +++ b/crates/hir-expand/src/mod_path.rs @@ -144,6 +144,12 @@ impl ModPath { } } +impl Extend for ModPath { + fn extend>(&mut self, iter: T) { + self.segments.extend(iter); + } +} + struct Display<'a> { db: &'a dyn ExpandDatabase, path: &'a ModPath, diff --git a/crates/hir-ty/Cargo.toml b/crates/hir-ty/Cargo.toml index 1f8f8744f9eb..41e2f7ad73c3 100644 --- a/crates/hir-ty/Cargo.toml +++ b/crates/hir-ty/Cargo.toml @@ -45,7 +45,6 @@ intern.workspace = true hir-def.workspace = true hir-expand.workspace = true base-db.workspace = true -profile.workspace = true syntax.workspace = true limit.workspace = true diff --git a/crates/hir/Cargo.toml b/crates/hir/Cargo.toml index 7fea8372876e..190722075a20 100644 --- a/crates/hir/Cargo.toml +++ b/crates/hir/Cargo.toml @@ -27,7 +27,6 @@ cfg.workspace = true hir-def.workspace = true hir-expand.workspace = true hir-ty.workspace = true -profile.workspace = true stdx.workspace = true syntax.workspace = true tt.workspace = true diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 5c607030167f..1e16f78ca2d3 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -126,7 +126,7 @@ pub use { }, hir_expand::{ attrs::{Attr, AttrId}, - change::Change, + change::ChangeWithProcMacros, hygiene::{marks_rev, SyntaxContextExt}, name::{known, Name}, proc_macro::ProcMacros, diff --git a/crates/ide-assists/Cargo.toml b/crates/ide-assists/Cargo.toml index 98961a18de25..e1375f9c3ee8 100644 --- a/crates/ide-assists/Cargo.toml +++ b/crates/ide-assists/Cargo.toml @@ -23,7 +23,6 @@ tracing.workspace = true stdx.workspace = true syntax.workspace = true text-edit.workspace = true -profile.workspace = true ide-db.workspace = true hir.workspace = true diff --git a/crates/ide-completion/Cargo.toml b/crates/ide-completion/Cargo.toml index f2a11276ba2b..6a4c70d460f2 100644 --- a/crates/ide-completion/Cargo.toml +++ b/crates/ide-completion/Cargo.toml @@ -23,7 +23,6 @@ smallvec.workspace = true # local deps base-db.workspace = true ide-db.workspace = true -profile.workspace = true stdx.workspace = true syntax.workspace = true text-edit.workspace = true diff --git a/crates/ide-db/src/apply_change.rs b/crates/ide-db/src/apply_change.rs index 2b2df144d6dd..f769f72d462d 100644 --- a/crates/ide-db/src/apply_change.rs +++ b/crates/ide-db/src/apply_change.rs @@ -11,7 +11,7 @@ use profile::{memory_usage, Bytes}; use rustc_hash::FxHashSet; use triomphe::Arc; -use crate::{symbol_index::SymbolsDatabase, Change, RootDatabase}; +use crate::{symbol_index::SymbolsDatabase, ChangeWithProcMacros, RootDatabase}; impl RootDatabase { pub fn request_cancellation(&mut self) { @@ -20,7 +20,7 @@ impl RootDatabase { self.synthetic_write(Durability::LOW); } - pub fn apply_change(&mut self, change: Change) { + pub fn apply_change(&mut self, change: ChangeWithProcMacros) { let _p = tracing::span!(tracing::Level::INFO, "RootDatabase::apply_change").entered(); self.request_cancellation(); tracing::trace!("apply_change {:?}", change); diff --git a/crates/ide-db/src/lib.rs b/crates/ide-db/src/lib.rs index 3e6cb7476bbb..a9f7e58de951 100644 --- a/crates/ide-db/src/lib.rs +++ b/crates/ide-db/src/lib.rs @@ -44,7 +44,7 @@ pub mod syntax_helpers { pub use parser::LexedStr; } -pub use hir::Change; +pub use hir::ChangeWithProcMacros; use std::{fmt, mem::ManuallyDrop}; diff --git a/crates/ide-diagnostics/Cargo.toml b/crates/ide-diagnostics/Cargo.toml index 69768041389a..509c5a152f72 100644 --- a/crates/ide-diagnostics/Cargo.toml +++ b/crates/ide-diagnostics/Cargo.toml @@ -20,7 +20,6 @@ tracing.workspace = true once_cell = "1.17.0" # local deps -profile.workspace = true stdx.workspace = true syntax.workspace = true text-edit.workspace = true diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index a076c7ca9fa4..4eb4acdf183c 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -61,7 +61,7 @@ use std::ffi::OsStr; use cfg::CfgOptions; use fetch_crates::CrateInfo; -use hir::Change; +use hir::ChangeWithProcMacros; use ide_db::{ base_db::{ salsa::{self, ParallelDatabase}, @@ -184,7 +184,7 @@ impl AnalysisHost { /// Applies changes to the current state of the world. If there are /// outstanding snapshots, they will be canceled. - pub fn apply_change(&mut self, change: Change) { + pub fn apply_change(&mut self, change: ChangeWithProcMacros) { self.db.apply_change(change); } @@ -239,7 +239,7 @@ impl Analysis { file_set.insert(file_id, VfsPath::new_virtual_path("/main.rs".to_owned())); let source_root = SourceRoot::new_local(file_set); - let mut change = Change::new(); + let mut change = ChangeWithProcMacros::new(); change.set_roots(vec![source_root]); let mut crate_graph = CrateGraph::default(); // FIXME: cfg options diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs index 2b5f515c3ad5..29c1251cceee 100644 --- a/crates/load-cargo/src/lib.rs +++ b/crates/load-cargo/src/lib.rs @@ -11,7 +11,7 @@ use hir_expand::proc_macro::{ }; use ide_db::{ base_db::{CrateGraph, Env, SourceRoot}, - prime_caches, Change, FxHashMap, RootDatabase, + prime_caches, ChangeWithProcMacros, FxHashMap, RootDatabase, }; use itertools::Itertools; use proc_macro_api::{MacroDylib, ProcMacroServer}; @@ -314,7 +314,7 @@ fn load_crate_graph( let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::().ok()); let mut db = RootDatabase::new(lru_cap); - let mut analysis_change = Change::new(); + let mut analysis_change = ChangeWithProcMacros::new(); db.enable_proc_attr_macros(); diff --git a/crates/parser/Cargo.toml b/crates/parser/Cargo.toml index e74b340126c0..1f84e3f3af3f 100644 --- a/crates/parser/Cargo.toml +++ b/crates/parser/Cargo.toml @@ -15,6 +15,7 @@ doctest = false drop_bomb = "0.1.5" ra-ap-rustc_lexer.workspace = true limit.workspace = true +tracing = { workspace = true, optional = true } [dev-dependencies] expect-test = "1.4.0" @@ -23,6 +24,7 @@ stdx.workspace = true sourcegen.workspace = true [features] +default = ["tracing"] in-rust-tree = [] [lints] diff --git a/crates/parser/src/lexed_str.rs b/crates/parser/src/lexed_str.rs index 2da9184693d9..48e4c8a6225c 100644 --- a/crates/parser/src/lexed_str.rs +++ b/crates/parser/src/lexed_str.rs @@ -31,6 +31,7 @@ struct LexError { impl<'a> LexedStr<'a> { pub fn new(text: &'a str) -> LexedStr<'a> { + let _p = tracing::span!(tracing::Level::INFO, "LexedStr::new").entered(); let mut conv = Converter::new(text); if let Some(shebang_len) = rustc_lexer::strip_shebang(text) { conv.res.push(SHEBANG, conv.offset); diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index 3ca285e787e8..86c771c00085 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -87,6 +87,7 @@ pub enum TopEntryPoint { impl TopEntryPoint { pub fn parse(&self, input: &Input) -> Output { + let _p = tracing::span!(tracing::Level::INFO, "TopEntryPoint::parse", ?self).entered(); let entry_point: fn(&'_ mut parser::Parser<'_>) = match self { TopEntryPoint::SourceFile => grammar::entry::top::source_file, TopEntryPoint::MacroStmts => grammar::entry::top::macro_stmts, diff --git a/crates/parser/src/shortcuts.rs b/crates/parser/src/shortcuts.rs index 57005a6834c9..680a70997d4b 100644 --- a/crates/parser/src/shortcuts.rs +++ b/crates/parser/src/shortcuts.rs @@ -26,6 +26,7 @@ pub enum StrStep<'a> { impl LexedStr<'_> { pub fn to_input(&self) -> crate::Input { + let _p = tracing::span!(tracing::Level::INFO, "LexedStr::to_input").entered(); let mut res = crate::Input::default(); let mut was_joint = false; for i in 0..self.len() { diff --git a/crates/proc-macro-api/Cargo.toml b/crates/proc-macro-api/Cargo.toml index cf01b94c0a2c..e98d70776c95 100644 --- a/crates/proc-macro-api/Cargo.toml +++ b/crates/proc-macro-api/Cargo.toml @@ -32,7 +32,6 @@ indexmap = "2.1.0" paths.workspace = true tt.workspace = true stdx.workspace = true -profile.workspace = true text-size.workspace = true span.workspace = true # Ideally this crate would not depend on salsa things, but we need span information here which wraps diff --git a/crates/profile/src/lib.rs b/crates/profile/src/lib.rs index 363998156063..a3fdb72a6d1d 100644 --- a/crates/profile/src/lib.rs +++ b/crates/profile/src/lib.rs @@ -23,29 +23,6 @@ pub use countme::Count; thread_local!(static IN_SCOPE: RefCell = const { RefCell::new(false) }); -/// Allows to check if the current code is within some dynamic scope, can be -/// useful during debugging to figure out why a function is called. -pub struct Scope { - prev: bool, -} - -impl Scope { - #[must_use] - pub fn enter() -> Scope { - let prev = IN_SCOPE.with(|slot| std::mem::replace(&mut *slot.borrow_mut(), true)); - Scope { prev } - } - pub fn is_active() -> bool { - IN_SCOPE.with(|slot| *slot.borrow()) - } -} - -impl Drop for Scope { - fn drop(&mut self) { - IN_SCOPE.with(|slot| *slot.borrow_mut() = self.prev); - } -} - /// A wrapper around google_cpu_profiler. /// /// Usage: diff --git a/crates/project-model/Cargo.toml b/crates/project-model/Cargo.toml index 3552ed191628..924a4a89e216 100644 --- a/crates/project-model/Cargo.toml +++ b/crates/project-model/Cargo.toml @@ -27,7 +27,6 @@ itertools.workspace = true base-db.workspace = true cfg.workspace = true paths.workspace = true -profile.workspace = true stdx.workspace = true toolchain.workspace = true @@ -35,4 +34,4 @@ toolchain.workspace = true expect-test = "1.4.0" [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/rust-analyzer/src/cli/rustc_tests.rs b/crates/rust-analyzer/src/cli/rustc_tests.rs index 9276d241affd..7ad87ab97fc6 100644 --- a/crates/rust-analyzer/src/cli/rustc_tests.rs +++ b/crates/rust-analyzer/src/cli/rustc_tests.rs @@ -5,7 +5,7 @@ use std::thread::Builder; use std::time::{Duration, Instant}; use std::{cell::RefCell, fs::read_to_string, panic::AssertUnwindSafe, path::PathBuf}; -use hir::{Change, Crate}; +use hir::{ChangeWithProcMacros, Crate}; use ide::{AnalysisHost, DiagnosticCode, DiagnosticsConfig}; use itertools::Either; use profile::StopWatch; @@ -122,7 +122,7 @@ impl Tester { FxHashMap::default() }; let text = read_to_string(&p).unwrap(); - let mut change = Change::new(); + let mut change = ChangeWithProcMacros::new(); // Ignore unstable tests, since they move too fast and we do not intend to support all of them. let mut ignore_test = text.contains("#![feature"); // Ignore test with extern crates, as this infra don't support them yet. diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index b2d507491b17..eb4727920533 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -7,7 +7,7 @@ use std::{collections::hash_map::Entry, time::Instant}; use crossbeam_channel::{unbounded, Receiver, Sender}; use flycheck::FlycheckHandle; -use hir::Change; +use hir::ChangeWithProcMacros; use ide::{Analysis, AnalysisHost, Cancellable, FileId}; use ide_db::base_db::{CrateId, ProcMacroPaths}; use load_cargo::SourceRootConfig; @@ -238,7 +238,7 @@ impl GlobalState { let mut file_changes = FxHashMap::<_, (bool, ChangedFile)>::default(); let (change, modified_rust_files, workspace_structure_change) = { - let mut change = Change::new(); + let mut change = ChangeWithProcMacros::new(); let mut guard = self.vfs.write(); let changed_files = guard.0.take_changes(); if changed_files.is_empty() { diff --git a/crates/rust-analyzer/src/integrated_benchmarks.rs b/crates/rust-analyzer/src/integrated_benchmarks.rs index 9d692175203d..008c63c35a6d 100644 --- a/crates/rust-analyzer/src/integrated_benchmarks.rs +++ b/crates/rust-analyzer/src/integrated_benchmarks.rs @@ -10,7 +10,7 @@ //! in release mode in VS Code. There's however "rust-analyzer: Copy Run Command Line" //! which you can use to paste the command in terminal and add `--release` manually. -use hir::Change; +use hir::ChangeWithProcMacros; use ide::{AnalysisHost, CallableSnippets, CompletionConfig, FilePosition, TextSize}; use ide_db::{ imports::insert_use::{ImportGranularity, InsertUseConfig}, @@ -55,19 +55,19 @@ fn integrated_highlighting_benchmark() { vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}")) }; + crate::tracing::hprof::init("*>100"); + { let _it = stdx::timeit("initial"); let analysis = host.analysis(); analysis.highlight_as_html(file_id, false).unwrap(); } - crate::tracing::hprof::init("*>100"); - { let _it = stdx::timeit("change"); let mut text = host.analysis().file_text(file_id).unwrap().to_string(); text.push_str("\npub fn _dummy() {}\n"); - let mut change = Change::new(); + let mut change = ChangeWithProcMacros::new(); change.change_file(file_id, Some(Arc::from(text))); host.apply_change(change); } @@ -120,7 +120,7 @@ fn integrated_completion_benchmark() { let completion_offset = patch(&mut text, "db.struct_data(self.id)", "sel;\ndb.struct_data(self.id)") + "sel".len(); - let mut change = Change::new(); + let mut change = ChangeWithProcMacros::new(); change.change_file(file_id, Some(Arc::from(text))); host.apply_change(change); completion_offset @@ -163,7 +163,7 @@ fn integrated_completion_benchmark() { let completion_offset = patch(&mut text, "sel;\ndb.struct_data(self.id)", ";sel;\ndb.struct_data(self.id)") + ";sel".len(); - let mut change = Change::new(); + let mut change = ChangeWithProcMacros::new(); change.change_file(file_id, Some(Arc::from(text))); host.apply_change(change); completion_offset @@ -205,7 +205,7 @@ fn integrated_completion_benchmark() { let completion_offset = patch(&mut text, "sel;\ndb.struct_data(self.id)", "self.;\ndb.struct_data(self.id)") + "self.".len(); - let mut change = Change::new(); + let mut change = ChangeWithProcMacros::new(); change.change_file(file_id, Some(Arc::from(text))); host.apply_change(change); completion_offset diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index f6bc032c0198..95d51baab387 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -16,7 +16,7 @@ use std::{iter, mem}; use flycheck::{FlycheckConfig, FlycheckHandle}; -use hir::{db::DefDatabase, Change, ProcMacros}; +use hir::{db::DefDatabase, ChangeWithProcMacros, ProcMacros}; use ide::CrateId; use ide_db::{ base_db::{salsa::Durability, CrateGraph, ProcMacroPaths, Version}, @@ -357,7 +357,7 @@ impl GlobalState { } pub(crate) fn set_proc_macros(&mut self, proc_macros: ProcMacros) { - let mut change = Change::new(); + let mut change = ChangeWithProcMacros::new(); change.set_proc_macros(proc_macros); self.analysis_host.apply_change(change); } @@ -548,7 +548,7 @@ impl GlobalState { ws_to_crate_graph(&self.workspaces, self.config.extra_env(), load) }; - let mut change = Change::new(); + let mut change = ChangeWithProcMacros::new(); if self.config.expand_proc_macros() { change.set_proc_macros( crate_graph diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml index a0fd73ee13f5..9a8d73cf7ff4 100644 --- a/crates/syntax/Cargo.toml +++ b/crates/syntax/Cargo.toml @@ -27,7 +27,6 @@ tracing.workspace = true ra-ap-rustc_lexer.workspace = true parser.workspace = true -profile.workspace = true stdx.workspace = true text-edit.workspace = true diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs index b755de86d32c..e8bb9ee938f9 100644 --- a/crates/syntax/src/lib.rs +++ b/crates/syntax/src/lib.rs @@ -168,6 +168,7 @@ pub use crate::ast::SourceFile; impl SourceFile { pub fn parse(text: &str) -> Parse { + let _p = tracing::span!(tracing::Level::INFO, "SourceFile::parse").entered(); let (green, mut errors) = parsing::parse_text(text); let root = SyntaxNode::new_root(green.clone()); diff --git a/crates/syntax/src/parsing.rs b/crates/syntax/src/parsing.rs index 1250b5274c18..d750476f63cb 100644 --- a/crates/syntax/src/parsing.rs +++ b/crates/syntax/src/parsing.rs @@ -10,6 +10,7 @@ use crate::{syntax_node::GreenNode, SyntaxError, SyntaxTreeBuilder}; pub(crate) use crate::parsing::reparsing::incremental_reparse; pub(crate) fn parse_text(text: &str) -> (GreenNode, Vec) { + let _p = tracing::span!(tracing::Level::INFO, "parse_text").entered(); let lexed = parser::LexedStr::new(text); let parser_input = lexed.to_input(); let parser_output = parser::TopEntryPoint::SourceFile.parse(&parser_input); @@ -21,6 +22,7 @@ pub(crate) fn build_tree( lexed: parser::LexedStr<'_>, parser_output: parser::Output, ) -> (GreenNode, Vec, bool) { + let _p = tracing::span!(tracing::Level::INFO, "build_tree").entered(); let mut builder = SyntaxTreeBuilder::default(); let is_eof = lexed.intersperse_trivia(&parser_output, &mut |step| match step { diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs index 5c5b26f525f6..5b3f449eeeb3 100644 --- a/crates/syntax/src/validation.rs +++ b/crates/syntax/src/validation.rs @@ -16,6 +16,7 @@ use crate::{ }; pub(crate) fn validate(root: &SyntaxNode) -> Vec { + let _p = tracing::span!(tracing::Level::INFO, "parser::validate").entered(); // FIXME: // * Add unescape validation of raw string literals and raw byte string literals // * Add validation of doc comments are being attached to nodes diff --git a/crates/test-fixture/src/lib.rs b/crates/test-fixture/src/lib.rs index e118262b4edd..ca3007d43704 100644 --- a/crates/test-fixture/src/lib.rs +++ b/crates/test-fixture/src/lib.rs @@ -7,7 +7,7 @@ use base_db::{ }; use cfg::CfgOptions; use hir_expand::{ - change::Change, + change::ChangeWithProcMacros, db::ExpandDatabase, proc_macro::{ ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind, ProcMacros, @@ -103,7 +103,7 @@ impl WithFixture for pub struct ChangeFixture { pub file_position: Option<(FileId, RangeOrOffset)>, pub files: Vec, - pub change: Change, + pub change: ChangeWithProcMacros, } const SOURCE_ROOT_PREFIX: &str = "/"; @@ -317,7 +317,7 @@ impl ChangeFixture { }; roots.push(root); - let mut change = Change { + let mut change = ChangeWithProcMacros { source_change, proc_macros: proc_macros.is_empty().not().then_some(proc_macros), toolchains: Some(iter::repeat(toolchain).take(crate_graph.len()).collect()), From c3c9f5ffe11af3a3be91734b3254eeaad283be8b Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 4 Mar 2024 11:39:38 +0100 Subject: [PATCH 22/69] internal: Compute syntax validation errors on demand --- crates/hir-def/src/data.rs | 5 ++-- crates/hir-def/src/nameres/collector.rs | 6 ++-- crates/hir-def/src/nameres/diagnostics.rs | 7 ++--- crates/hir-expand/src/db.rs | 4 +-- crates/hir-expand/src/files.rs | 2 +- crates/ide-diagnostics/src/lib.rs | 2 +- .../src/integrated_benchmarks.rs | 4 ++- crates/rust-analyzer/src/tracing/hprof.rs | 4 +-- crates/syntax/src/lib.rs | 21 ++++++------- crates/syntax/src/tests.rs | 4 +-- crates/syntax/src/validation.rs | 30 +++++++++---------- 11 files changed, 45 insertions(+), 44 deletions(-) diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index f506864902c4..d4c1db8b95b4 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -788,11 +788,12 @@ impl<'a> AssocItemCollector<'a> { }; self.diagnostics.push(diag); } - if let errors @ [_, ..] = parse.errors() { + let errors = parse.errors(); + if !errors.is_empty() { self.diagnostics.push(DefDiagnostic::macro_expansion_parse_error( self.module_id.local_id, error_call_kind(), - errors, + errors.into_boxed_slice(), )); } diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 18aefbf332c8..f9fe6d3b903b 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -1384,7 +1384,9 @@ impl DefCollector<'_> { // First, fetch the raw expansion result for purposes of error reporting. This goes through // `parse_macro_expansion_error` to avoid depending on the full expansion result (to improve // incrementality). - let ExpandResult { value, err } = self.db.parse_macro_expansion_error(macro_call_id); + // FIXME: This kind of error fetching feels a bit odd? + let ExpandResult { value: errors, err } = + self.db.parse_macro_expansion_error(macro_call_id); if let Some(err) = err { let loc: MacroCallLoc = self.db.lookup_intern_macro_call(macro_call_id); let diag = match err { @@ -1398,7 +1400,7 @@ impl DefCollector<'_> { self.def_map.diagnostics.push(diag); } - if let errors @ [_, ..] = &*value { + if !errors.is_empty() { let loc: MacroCallLoc = self.db.lookup_intern_macro_call(macro_call_id); let diag = DefDiagnostic::macro_expansion_parse_error(module_id, loc.kind, errors); self.def_map.diagnostics.push(diag); diff --git a/crates/hir-def/src/nameres/diagnostics.rs b/crates/hir-def/src/nameres/diagnostics.rs index b5a302dbcaf6..8c7fdaaf58b3 100644 --- a/crates/hir-def/src/nameres/diagnostics.rs +++ b/crates/hir-def/src/nameres/diagnostics.rs @@ -117,14 +117,11 @@ impl DefDiagnostic { pub(crate) fn macro_expansion_parse_error( container: LocalModuleId, ast: MacroCallKind, - errors: &[SyntaxError], + errors: Box<[SyntaxError]>, ) -> Self { Self { in_module: container, - kind: DefDiagnosticKind::MacroExpansionParseError { - ast, - errors: errors.to_vec().into_boxed_slice(), - }, + kind: DefDiagnosticKind::MacroExpansionParseError { ast, errors }, } } diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs index f1f0d8990f1c..3a65bc7c6ea2 100644 --- a/crates/hir-expand/src/db.rs +++ b/crates/hir-expand/src/db.rs @@ -303,7 +303,7 @@ fn parse_macro_expansion_error( macro_call_id: MacroCallId, ) -> ExpandResult> { db.parse_macro_expansion(MacroFileId { macro_call_id }) - .map(|it| it.0.errors().to_vec().into_boxed_slice()) + .map(|it| it.0.errors().into_boxed_slice()) } pub(crate) fn parse_with_map( @@ -445,7 +445,7 @@ fn macro_arg( if matches!(loc.def.kind, MacroDefKind::BuiltInEager(..)) { match parse.errors() { - [] => ValueResult::ok((Arc::new(tt), undo_info)), + errors if errors.is_empty() => ValueResult::ok((Arc::new(tt), undo_info)), errors => ValueResult::new( (Arc::new(tt), undo_info), // Box::<[_]>::from(res.errors()), not stable yet diff --git a/crates/hir-expand/src/files.rs b/crates/hir-expand/src/files.rs index 66ceb1b7d420..a500c24ce881 100644 --- a/crates/hir-expand/src/files.rs +++ b/crates/hir-expand/src/files.rs @@ -252,7 +252,7 @@ impl InFile<&SyntaxNode> { map_node_range_up(db, &db.expansion_span_map(file_id), self.value.text_range())?; // FIXME: Figure out an API that makes proper use of ctx, this only exists to - // keep pre-token map rewrite behaviour. + // keep pre-token map rewrite behavior. if !ctx.is_root() { return None; } diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs index 9f4368b04e79..486bf6f95c45 100644 --- a/crates/ide-diagnostics/src/lib.rs +++ b/crates/ide-diagnostics/src/lib.rs @@ -299,7 +299,7 @@ pub fn diagnostics( let mut res = Vec::new(); // [#34344] Only take first 128 errors to prevent slowing down editor/ide, the number 128 is chosen arbitrarily. - res.extend(parse.errors().iter().take(128).map(|err| { + res.extend(parse.errors().into_iter().take(128).map(|err| { Diagnostic::new( DiagnosticCode::RustcHardError("syntax-error"), format!("Syntax Error: {err}"), diff --git a/crates/rust-analyzer/src/integrated_benchmarks.rs b/crates/rust-analyzer/src/integrated_benchmarks.rs index 008c63c35a6d..28eae6079c54 100644 --- a/crates/rust-analyzer/src/integrated_benchmarks.rs +++ b/crates/rust-analyzer/src/integrated_benchmarks.rs @@ -55,7 +55,7 @@ fn integrated_highlighting_benchmark() { vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}")) }; - crate::tracing::hprof::init("*>100"); + let _g = crate::tracing::hprof::init("*>150"); { let _it = stdx::timeit("initial"); @@ -72,6 +72,8 @@ fn integrated_highlighting_benchmark() { host.apply_change(change); } + let _g = crate::tracing::hprof::init("*>50"); + { let _it = stdx::timeit("after change"); let _span = profile::cpu_span(); diff --git a/crates/rust-analyzer/src/tracing/hprof.rs b/crates/rust-analyzer/src/tracing/hprof.rs index 906498732977..5fcda6ba136a 100644 --- a/crates/rust-analyzer/src/tracing/hprof.rs +++ b/crates/rust-analyzer/src/tracing/hprof.rs @@ -52,7 +52,7 @@ use tracing_subscriber::{ use crate::tracing::hprof; -pub fn init(spec: &str) { +pub fn init(spec: &str) -> tracing::subscriber::DefaultGuard { let (write_filter, allowed_names) = WriteFilter::from_spec(spec); // this filter the first pass for `tracing`: these are all the "profiling" spans, but things like @@ -76,7 +76,7 @@ pub fn init(spec: &str) { .with_filter(profile_filter); let subscriber = Registry::default().with(layer); - tracing::subscriber::set_global_default(subscriber).unwrap(); + tracing::subscriber::set_default(subscriber) } #[derive(Default, Debug)] diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs index e8bb9ee938f9..1bb82cc191ff 100644 --- a/crates/syntax/src/lib.rs +++ b/crates/syntax/src/lib.rs @@ -97,8 +97,11 @@ impl Parse { pub fn syntax_node(&self) -> SyntaxNode { SyntaxNode::new_root(self.green.clone()) } - pub fn errors(&self) -> &[SyntaxError] { - self.errors.as_deref().unwrap_or_default() + + pub fn errors(&self) -> Vec { + let mut errors = if let Some(e) = self.errors.as_deref() { e.to_vec() } else { vec![] }; + validation::validate(&self.syntax_node(), &mut errors); + errors } } @@ -111,10 +114,10 @@ impl Parse { T::cast(self.syntax_node()).unwrap() } - pub fn ok(self) -> Result> { - match self.errors { - Some(e) => Err(e), - None => Ok(self.tree()), + pub fn ok(self) -> Result> { + match self.errors() { + errors if !errors.is_empty() => Err(errors), + _ => Ok(self.tree()), } } } @@ -132,7 +135,7 @@ impl Parse { impl Parse { pub fn debug_dump(&self) -> String { let mut buf = format!("{:#?}", self.tree().syntax()); - for err in self.errors.as_deref().into_iter().flat_map(<[_]>::iter) { + for err in self.errors() { format_to!(buf, "error {:?}: {}\n", err.range(), err); } buf @@ -169,11 +172,9 @@ pub use crate::ast::SourceFile; impl SourceFile { pub fn parse(text: &str) -> Parse { let _p = tracing::span!(tracing::Level::INFO, "SourceFile::parse").entered(); - let (green, mut errors) = parsing::parse_text(text); + let (green, errors) = parsing::parse_text(text); let root = SyntaxNode::new_root(green.clone()); - errors.extend(validation::validate(&root)); - assert_eq!(root.kind(), SyntaxKind::SOURCE_FILE); Parse { green, diff --git a/crates/syntax/src/tests.rs b/crates/syntax/src/tests.rs index 4c0a538f712f..5400071c4b67 100644 --- a/crates/syntax/src/tests.rs +++ b/crates/syntax/src/tests.rs @@ -39,7 +39,7 @@ fn benchmark_parser() { let tree = { let _b = bench("parsing"); let p = SourceFile::parse(&data); - assert!(p.errors.is_none()); + assert!(p.errors().is_empty()); assert_eq!(p.tree().syntax.text_range().len(), 352474.into()); p.tree() }; @@ -57,7 +57,7 @@ fn validation_tests() { dir_tests(&test_data_dir(), &["parser/validation"], "rast", |text, path| { let parse = SourceFile::parse(text); let errors = parse.errors(); - assert_errors_are_present(errors, path); + assert_errors_are_present(&errors, path); parse.debug_dump() }); } diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs index 5b3f449eeeb3..dbfab537fe58 100644 --- a/crates/syntax/src/validation.rs +++ b/crates/syntax/src/validation.rs @@ -15,34 +15,32 @@ use crate::{ SyntaxNode, SyntaxToken, TextSize, T, }; -pub(crate) fn validate(root: &SyntaxNode) -> Vec { +pub(crate) fn validate(root: &SyntaxNode, errors: &mut Vec) { let _p = tracing::span!(tracing::Level::INFO, "parser::validate").entered(); // FIXME: // * Add unescape validation of raw string literals and raw byte string literals // * Add validation of doc comments are being attached to nodes - let mut errors = Vec::new(); for node in root.descendants() { match_ast! { match node { - ast::Literal(it) => validate_literal(it, &mut errors), - ast::Const(it) => validate_const(it, &mut errors), - ast::BlockExpr(it) => block::validate_block_expr(it, &mut errors), - ast::FieldExpr(it) => validate_numeric_name(it.name_ref(), &mut errors), - ast::RecordExprField(it) => validate_numeric_name(it.name_ref(), &mut errors), - ast::Visibility(it) => validate_visibility(it, &mut errors), - ast::RangeExpr(it) => validate_range_expr(it, &mut errors), - ast::PathSegment(it) => validate_path_keywords(it, &mut errors), - ast::RefType(it) => validate_trait_object_ref_ty(it, &mut errors), - ast::PtrType(it) => validate_trait_object_ptr_ty(it, &mut errors), - ast::FnPtrType(it) => validate_trait_object_fn_ptr_ret_ty(it, &mut errors), - ast::MacroRules(it) => validate_macro_rules(it, &mut errors), - ast::LetExpr(it) => validate_let_expr(it, &mut errors), + ast::Literal(it) => validate_literal(it, errors), + ast::Const(it) => validate_const(it, errors), + ast::BlockExpr(it) => block::validate_block_expr(it, errors), + ast::FieldExpr(it) => validate_numeric_name(it.name_ref(), errors), + ast::RecordExprField(it) => validate_numeric_name(it.name_ref(), errors), + ast::Visibility(it) => validate_visibility(it, errors), + ast::RangeExpr(it) => validate_range_expr(it, errors), + ast::PathSegment(it) => validate_path_keywords(it, errors), + ast::RefType(it) => validate_trait_object_ref_ty(it, errors), + ast::PtrType(it) => validate_trait_object_ptr_ty(it, errors), + ast::FnPtrType(it) => validate_trait_object_fn_ptr_ret_ty(it, errors), + ast::MacroRules(it) => validate_macro_rules(it, errors), + ast::LetExpr(it) => validate_let_expr(it, errors), _ => (), } } } - errors } fn rustc_unescape_error_to_string(err: unescape::EscapeError) -> (&'static str, bool) { From 6e802a0b5652934fe367224c26a2d8809e33d503 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 4 Mar 2024 16:35:33 +0100 Subject: [PATCH 23/69] minor: Mark remove_unnecessary_else as experimental --- crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs b/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs index 47844876dc54..f68e69823856 100644 --- a/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs +++ b/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs @@ -30,6 +30,7 @@ pub(crate) fn remove_unnecessary_else( "remove unnecessary else block", display_range, ) + .experimental() .with_fixes(fixes(ctx, d)) } From 0964374274a64ad15c640d57982d74ce66c58b84 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 4 Mar 2024 16:49:03 +0100 Subject: [PATCH 24/69] Move diagnostics docs generation into xtask/codegen --- Cargo.lock | 1 - crates/ide-assists/Cargo.toml | 3 -- crates/ide-diagnostics/Cargo.toml | 4 --- crates/ide/Cargo.toml | 3 -- crates/rust-analyzer/Cargo.toml | 1 - xtask/src/codegen.rs | 1 + .../src/codegen/diagnostics_docs.rs | 28 +++++++++++-------- 7 files changed, 17 insertions(+), 24 deletions(-) rename crates/ide-diagnostics/src/tests/sourcegen.rs => xtask/src/codegen/diagnostics_docs.rs (71%) diff --git a/Cargo.lock b/Cargo.lock index 9b431d85a647..45f4aa89117f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -747,7 +747,6 @@ dependencies = [ "itertools", "once_cell", "serde_json", - "sourcegen", "stdx", "syntax", "test-fixture", diff --git a/crates/ide-assists/Cargo.toml b/crates/ide-assists/Cargo.toml index a78129fc47ef..b1e7609afef4 100644 --- a/crates/ide-assists/Cargo.toml +++ b/crates/ide-assists/Cargo.toml @@ -33,8 +33,5 @@ expect-test = "1.4.0" test-utils.workspace = true test-fixture.workspace = true -[features] -in-rust-tree = [] - [lints] workspace = true diff --git a/crates/ide-diagnostics/Cargo.toml b/crates/ide-diagnostics/Cargo.toml index 509c5a152f72..8ccea99e9e13 100644 --- a/crates/ide-diagnostics/Cargo.toml +++ b/crates/ide-diagnostics/Cargo.toml @@ -33,10 +33,6 @@ expect-test = "1.4.0" # local deps test-utils.workspace = true test-fixture.workspace = true -sourcegen.workspace = true - -[features] -in-rust-tree = [] [lints] workspace = true diff --git a/crates/ide/Cargo.toml b/crates/ide/Cargo.toml index bb06d614450f..eab3925aab65 100644 --- a/crates/ide/Cargo.toml +++ b/crates/ide/Cargo.toml @@ -51,8 +51,5 @@ expect-test = "1.4.0" test-utils.workspace = true test-fixture.workspace = true -[features] -in-rust-tree = ["ide-assists/in-rust-tree", "ide-diagnostics/in-rust-tree"] - [lints] workspace = true diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index a212041e66b4..766606be7bea 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml @@ -85,7 +85,6 @@ force-always-assert = ["always-assert/force"] sysroot-abi = [] in-rust-tree = [ "sysroot-abi", - "ide/in-rust-tree", "syntax/in-rust-tree", "parser/in-rust-tree", "hir/in-rust-tree", diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index e579660ac9b1..d51daa339573 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs @@ -8,6 +8,7 @@ use xshell::{cmd, Shell}; use crate::{flags, project_root}; pub(crate) mod assists_doc_tests; +pub(crate) mod diagnostics_docs; impl flags::Codegen { pub(crate) fn run(self, _sh: &Shell) -> anyhow::Result<()> { diff --git a/crates/ide-diagnostics/src/tests/sourcegen.rs b/xtask/src/codegen/diagnostics_docs.rs similarity index 71% rename from crates/ide-diagnostics/src/tests/sourcegen.rs rename to xtask/src/codegen/diagnostics_docs.rs index 9e7fcfc590b7..a45b412fda59 100644 --- a/crates/ide-diagnostics/src/tests/sourcegen.rs +++ b/xtask/src/codegen/diagnostics_docs.rs @@ -2,22 +2,26 @@ use std::{fmt, fs, io, path::PathBuf}; -use sourcegen::project_root; +use crate::{ + codegen::{add_preamble, list_rust_files, CommentBlock, Location}, + project_root, +}; -#[test] -fn sourcegen_diagnostic_docs() { +fn generate(check: bool) { let diagnostics = Diagnostic::collect().unwrap(); - let contents = - diagnostics.into_iter().map(|it| it.to_string()).collect::>().join("\n\n"); - let contents = sourcegen::add_preamble("sourcegen_diagnostic_docs", contents); - let dst = project_root().join("docs/user/generated_diagnostic.adoc"); - fs::write(dst, contents).unwrap(); + if !check { + let contents = + diagnostics.into_iter().map(|it| it.to_string()).collect::>().join("\n\n"); + let contents = add_preamble("sourcegen_diagnostic_docs", contents); + let dst = project_root().join("docs/user/generated_diagnostic.adoc"); + fs::write(dst, contents).unwrap(); + } } #[derive(Debug)] struct Diagnostic { id: String, - location: sourcegen::Location, + location: Location, doc: String, } @@ -26,7 +30,7 @@ impl Diagnostic { let handlers_dir = project_root().join("crates/ide-diagnostics/src/handlers"); let mut res = Vec::new(); - for path in sourcegen::list_rust_files(&handlers_dir) { + for path in list_rust_files(&handlers_dir) { collect_file(&mut res, path)?; } res.sort_by(|lhs, rhs| lhs.id.cmp(&rhs.id)); @@ -34,7 +38,7 @@ impl Diagnostic { fn collect_file(acc: &mut Vec, path: PathBuf) -> io::Result<()> { let text = fs::read_to_string(&path)?; - let comment_blocks = sourcegen::CommentBlock::extract("Diagnostic", &text); + let comment_blocks = CommentBlock::extract("Diagnostic", &text); for block in comment_blocks { let id = block.id; @@ -42,7 +46,7 @@ impl Diagnostic { panic!("invalid diagnostic name: {id:?}:\n {msg}") } let doc = block.contents.join("\n"); - let location = sourcegen::Location { file: path.clone(), line: block.line }; + let location = Location { file: path.clone(), line: block.line }; acc.push(Diagnostic { id, location, doc }) } From 76463eee48a0b6dcaac5cd95aff91251a1abf475 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 4 Mar 2024 17:02:28 +0100 Subject: [PATCH 25/69] Move lint definition generation into xtask/codegen --- Cargo.lock | 4 +- crates/ide-db/Cargo.toml | 3 -- crates/ide-db/src/lib.rs | 6 --- crates/ide-db/src/tests/line_index.rs | 49 ----------------- crates/ide-diagnostics/src/tests.rs | 2 - lib/line-index/Cargo.toml | 5 +- lib/line-index/src/tests.rs | 53 +++++++++++++++++++ xtask/src/codegen.rs | 6 +++ xtask/src/codegen/diagnostics_docs.rs | 2 +- .../src/codegen/lints.rs | 40 +++++++------- xtask/src/flags.rs | 4 ++ xtask/src/release.rs | 2 +- 12 files changed, 90 insertions(+), 86 deletions(-) delete mode 100644 crates/ide-db/src/tests/line_index.rs rename crates/ide-db/src/tests/sourcegen_lints.rs => xtask/src/codegen/lints.rs (93%) diff --git a/Cargo.lock b/Cargo.lock index 45f4aa89117f..89a1f68cce0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -717,12 +717,10 @@ dependencies = [ "memchr", "nohash-hasher", "once_cell", - "oorandom", "parser", "profile", "rayon", "rustc-hash", - "sourcegen", "span", "stdx", "syntax", @@ -731,7 +729,6 @@ dependencies = [ "text-edit", "tracing", "triomphe", - "xshell", ] [[package]] @@ -916,6 +913,7 @@ name = "line-index" version = "0.1.1" dependencies = [ "nohash-hasher", + "oorandom", "text-size", ] diff --git a/crates/ide-db/Cargo.toml b/crates/ide-db/Cargo.toml index b487b138fc0e..071e1b471793 100644 --- a/crates/ide-db/Cargo.toml +++ b/crates/ide-db/Cargo.toml @@ -44,13 +44,10 @@ line-index.workspace = true [dev-dependencies] expect-test = "1.4.0" -oorandom = "11.1.3" -xshell.workspace = true # local deps test-utils.workspace = true test-fixture.workspace = true -sourcegen.workspace = true [lints] workspace = true diff --git a/crates/ide-db/src/lib.rs b/crates/ide-db/src/lib.rs index a9f7e58de951..0d11858ed7f4 100644 --- a/crates/ide-db/src/lib.rs +++ b/crates/ide-db/src/lib.rs @@ -412,9 +412,3 @@ impl SnippetCap { } } } - -#[cfg(test)] -mod tests { - mod line_index; - mod sourcegen_lints; -} diff --git a/crates/ide-db/src/tests/line_index.rs b/crates/ide-db/src/tests/line_index.rs deleted file mode 100644 index 6b49bb2631c1..000000000000 --- a/crates/ide-db/src/tests/line_index.rs +++ /dev/null @@ -1,49 +0,0 @@ -use line_index::{LineCol, LineIndex, WideEncoding}; -use test_utils::skip_slow_tests; - -#[test] -fn test_every_chars() { - if skip_slow_tests() { - return; - } - - let text: String = { - let mut chars: Vec = ((0 as char)..char::MAX).collect(); // Neat! - chars.extend("\n".repeat(chars.len() / 16).chars()); - let mut rng = oorandom::Rand32::new(stdx::rand::seed()); - stdx::rand::shuffle(&mut chars, |i| rng.rand_range(0..i as u32) as usize); - chars.into_iter().collect() - }; - assert!(text.contains('💩')); // Sanity check. - - let line_index = LineIndex::new(&text); - - let mut lin_col = LineCol { line: 0, col: 0 }; - let mut col_utf16 = 0; - let mut col_utf32 = 0; - for (offset, c) in text.char_indices() { - let got_offset = line_index.offset(lin_col).unwrap(); - assert_eq!(usize::from(got_offset), offset); - - let got_lin_col = line_index.line_col(got_offset); - assert_eq!(got_lin_col, lin_col); - - for (enc, col) in [(WideEncoding::Utf16, col_utf16), (WideEncoding::Utf32, col_utf32)] { - let wide_lin_col = line_index.to_wide(enc, lin_col).unwrap(); - let got_lin_col = line_index.to_utf8(enc, wide_lin_col).unwrap(); - assert_eq!(got_lin_col, lin_col); - assert_eq!(wide_lin_col.col, col) - } - - if c == '\n' { - lin_col.line += 1; - lin_col.col = 0; - col_utf16 = 0; - col_utf32 = 0; - } else { - lin_col.col += c.len_utf8() as u32; - col_utf16 += c.len_utf16() as u32; - col_utf32 += 1; - } - } -} diff --git a/crates/ide-diagnostics/src/tests.rs b/crates/ide-diagnostics/src/tests.rs index 901ceffbb266..dcaa21208923 100644 --- a/crates/ide-diagnostics/src/tests.rs +++ b/crates/ide-diagnostics/src/tests.rs @@ -1,6 +1,4 @@ #![allow(clippy::print_stderr)] -#[cfg(not(feature = "in-rust-tree"))] -mod sourcegen; use ide_db::{ assists::AssistResolveStrategy, base_db::SourceDatabaseExt, LineIndexDatabase, RootDatabase, diff --git a/lib/line-index/Cargo.toml b/lib/line-index/Cargo.toml index 77e187de1ed8..8ae4954dd0de 100644 --- a/lib/line-index/Cargo.toml +++ b/lib/line-index/Cargo.toml @@ -10,5 +10,8 @@ edition = "2021" text-size = "1.1.1" nohash-hasher = "0.2.0" +[dev-dependencies] +oorandom = "11.1.3" + [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/lib/line-index/src/tests.rs b/lib/line-index/src/tests.rs index 981008e346ba..57fad1dfc057 100644 --- a/lib/line-index/src/tests.rs +++ b/lib/line-index/src/tests.rs @@ -142,3 +142,56 @@ fn test_to_wide() { let wide_line_col = line_index.to_wide(WideEncoding::Utf16, line_col.unwrap()); assert_eq!(wide_line_col, Some(WideLineCol { line: 5, col: 4 })); } + +#[test] +fn test_every_chars() { + let text: String = { + let mut chars: Vec = ((0 as char)..char::MAX).collect(); // Neat! + chars.extend("\n".repeat(chars.len() / 16).chars()); + let seed = std::hash::Hasher::finish(&std::hash::BuildHasher::build_hasher( + #[allow(clippy::disallowed_types)] + &std::collections::hash_map::RandomState::new(), + )); + let mut rng = oorandom::Rand32::new(seed); + let mut rand_index = |i| rng.rand_range(0..i as u32) as usize; + let mut remaining = chars.len() - 1; + while remaining > 0 { + let index = rand_index(remaining); + chars.swap(remaining, index); + remaining -= 1; + } + chars.into_iter().collect() + }; + assert!(text.contains('💩')); // Sanity check. + + let line_index = LineIndex::new(&text); + + let mut lin_col = LineCol { line: 0, col: 0 }; + let mut col_utf16 = 0; + let mut col_utf32 = 0; + for (offset, c) in text.char_indices() { + let got_offset = line_index.offset(lin_col).unwrap(); + assert_eq!(usize::from(got_offset), offset); + + let got_lin_col = line_index.line_col(got_offset); + assert_eq!(got_lin_col, lin_col); + + for (enc, col) in [(WideEncoding::Utf16, col_utf16), (WideEncoding::Utf32, col_utf32)] { + let wide_lin_col = line_index.to_wide(enc, lin_col).unwrap(); + let got_lin_col = line_index.to_utf8(enc, wide_lin_col).unwrap(); + assert_eq!(got_lin_col, lin_col); + assert_eq!(wide_lin_col.col, col) + } + + if c == '\n' { + lin_col.line += 1; + lin_col.col = 0; + col_utf16 = 0; + col_utf32 = 0; + } else { + lin_col.col += c.len_utf8() as u32; + col_utf16 += c.len_utf16() as u32; + col_utf32 += 1; + } + } +} diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index d51daa339573..40f872a24ab3 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs @@ -9,14 +9,20 @@ use crate::{flags, project_root}; pub(crate) mod assists_doc_tests; pub(crate) mod diagnostics_docs; +mod lints; impl flags::Codegen { pub(crate) fn run(self, _sh: &Shell) -> anyhow::Result<()> { match self.codegen_type.unwrap_or_default() { flags::CodegenType::All => { + diagnostics_docs::generate(self.check); assists_doc_tests::generate(self.check); + // lints::generate(self.check) Updating clones the rust repo, so don't run it unless + // explicitly asked for } flags::CodegenType::AssistsDocTests => assists_doc_tests::generate(self.check), + flags::CodegenType::DiagnosticsDocs => diagnostics_docs::generate(self.check), + flags::CodegenType::LintDefinitions => lints::generate(self.check), } Ok(()) } diff --git a/xtask/src/codegen/diagnostics_docs.rs b/xtask/src/codegen/diagnostics_docs.rs index a45b412fda59..cf30531e7f9f 100644 --- a/xtask/src/codegen/diagnostics_docs.rs +++ b/xtask/src/codegen/diagnostics_docs.rs @@ -7,7 +7,7 @@ use crate::{ project_root, }; -fn generate(check: bool) { +pub(crate) fn generate(check: bool) { let diagnostics = Diagnostic::collect().unwrap(); if !check { let contents = diff --git a/crates/ide-db/src/tests/sourcegen_lints.rs b/xtask/src/codegen/lints.rs similarity index 93% rename from crates/ide-db/src/tests/sourcegen_lints.rs rename to xtask/src/codegen/lints.rs index 86ed01c8e748..63abcfc09041 100644 --- a/crates/ide-db/src/tests/sourcegen_lints.rs +++ b/xtask/src/codegen/lints.rs @@ -2,18 +2,18 @@ //! and lints from rustc, rustdoc, and clippy. use std::{borrow::Cow, fs, path::Path}; -use itertools::Itertools; use stdx::format_to; -use test_utils::project_root; use xshell::{cmd, Shell}; +use crate::{ + codegen::{add_preamble, ensure_file_contents, list_files, reformat}, + project_root, +}; + const DESTINATION: &str = "crates/ide-db/src/generated/lints.rs"; -/// This clones rustc repo, and so is not worth to keep up-to-date. We update -/// manually by un-ignoring the test from time to time. -#[test] -#[ignore] -fn sourcegen_lint_completions() { +/// This clones rustc repo, and so is not worth to keep up-to-date on a constant basis. +pub(crate) fn generate(check: bool) { let sh = &Shell::new().unwrap(); let rust_repo = project_root().join("./target/rust"); @@ -73,10 +73,10 @@ pub struct LintGroup { .unwrap(); generate_descriptor_clippy(&mut contents, &lints_json); - let contents = sourcegen::add_preamble("sourcegen_lints", sourcegen::reformat(contents)); + let contents = add_preamble("sourcegen_lints", reformat(contents)); let destination = project_root().join(DESTINATION); - sourcegen::ensure_file_contents(destination.as_path(), &contents); + ensure_file_contents(destination.as_path(), &contents, check); } /// Parses the output of `rustdoc -Whelp` and prints `Lint` and `LintGroup` constants into `buf`. @@ -130,10 +130,9 @@ fn generate_lint_descriptor(sh: &Shell, buf: &mut String) { ) }); - let lints = lints - .chain(lint_groups) - .sorted_by(|(ident, ..), (ident2, ..)| ident.cmp(ident2)) - .collect::>(); + let mut lints = lints.chain(lint_groups).collect::>(); + lints.sort_by(|(ident, ..), (ident2, ..)| ident.cmp(ident2)); + for (name, description, ..) in &lints { push_lint_completion(buf, &name.replace('-', "_"), description); } @@ -177,10 +176,8 @@ fn generate_lint_descriptor(sh: &Shell, buf: &mut String) { ) }); - let lints_rustdoc = lints_rustdoc - .chain(lint_groups_rustdoc) - .sorted_by(|(ident, ..), (ident2, ..)| ident.cmp(ident2)) - .collect::>(); + let mut lints_rustdoc = lints_rustdoc.chain(lint_groups_rustdoc).collect::>(); + lints_rustdoc.sort_by(|(ident, ..), (ident2, ..)| ident.cmp(ident2)); for (name, description, ..) in &lints_rustdoc { push_lint_completion(buf, &name.replace('-', "_"), description) @@ -212,7 +209,7 @@ fn find_and_slice<'a>(i: &'a str, p: &str) -> &'a str { fn generate_feature_descriptor(buf: &mut String, src_dir: &Path) { let mut features = ["language-features", "library-features"] .into_iter() - .flat_map(|it| sourcegen::list_files(&src_dir.join(it))) + .flat_map(|it| list_files(&src_dir.join(it))) // Get all `.md` files .filter(|path| path.extension() == Some("md".as_ref())) .map(|path| { @@ -302,7 +299,7 @@ fn generate_descriptor_clippy(buf: &mut String, path: &Path) { let children = children.iter().map(|id| format!("clippy::{id}")).collect::>(); if !children.is_empty() { let lint_ident = format!("clippy::{id}"); - let description = format!("lint group for: {}", children.iter().join(", ")); + let description = format!("lint group for: {}", children.join(", ")); push_lint_group(buf, &lint_ident, &description, &children); } } @@ -331,7 +328,10 @@ fn push_lint_group(buf: &mut String, label: &str, description: &str, children: & push_lint_completion(buf, label, description); - let children = format!("&[{}]", children.iter().map(|it| format!("\"{it}\"")).join(", ")); + let children = format!( + "&[{}]", + children.iter().map(|it| format!("\"{it}\"")).collect::>().join(", ") + ); format_to!( buf, r###" diff --git a/xtask/src/flags.rs b/xtask/src/flags.rs index f5827170b651..681c588bd01b 100644 --- a/xtask/src/flags.rs +++ b/xtask/src/flags.rs @@ -92,6 +92,8 @@ pub enum CodegenType { #[default] All, AssistsDocTests, + DiagnosticsDocs, + LintDefinitions, } impl FromStr for CodegenType { @@ -100,6 +102,8 @@ impl FromStr for CodegenType { match s { "all" => Ok(Self::All), "assists-doc-tests" => Ok(Self::AssistsDocTests), + "diagnostics-docs" => Ok(Self::DiagnosticsDocs), + "lints-definitions" => Ok(Self::LintDefinitions), _ => Err("Invalid option".to_owned()), } } diff --git a/xtask/src/release.rs b/xtask/src/release.rs index f99f9ecbc39d..1a5e6dfb4ccf 100644 --- a/xtask/src/release.rs +++ b/xtask/src/release.rs @@ -23,7 +23,7 @@ impl flags::Release { } // Generates bits of manual.adoc. - cmd!(sh, "cargo test -p ide-diagnostics -p rust-analyzer -- sourcegen_").run()?; + codegen::diagnostics_docs::generate(false); codegen::assists_doc_tests::generate(false); let website_root = project_root().join("../rust-analyzer.github.io"); From b9dbb8afd9903b481f6902a1171d87a104b2e540 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 4 Mar 2024 17:12:08 +0100 Subject: [PATCH 26/69] Regenerate lints table --- crates/ide-db/src/generated/lints.rs | 420 +++++++++++++++++++++------ crates/ide/src/hover/tests.rs | 54 +++- 2 files changed, 383 insertions(+), 91 deletions(-) diff --git a/crates/ide-db/src/generated/lints.rs b/crates/ide-db/src/generated/lints.rs index 2fc079332003..d50088e6cf1d 100644 --- a/crates/ide-db/src/generated/lints.rs +++ b/crates/ide-db/src/generated/lints.rs @@ -22,6 +22,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ description: r##"detects certain glob imports that require reporting an ambiguity error"##, }, Lint { label: "ambiguous_glob_reexports", description: r##"ambiguous glob re-exports"## }, + Lint { + label: "ambiguous_wide_pointer_comparisons", + description: r##"detects ambiguous wide pointer comparisons"##, + }, Lint { label: "anonymous_parameters", description: r##"detects anonymous parameters"## }, Lint { label: "arithmetic_overflow", description: r##"arithmetic operation overflows"## }, Lint { @@ -66,10 +70,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "coherence_leak_check", description: r##"distinct impls distinguished only by the leak-check code"##, }, - Lint { - label: "coinductive_overlap_in_coherence", - description: r##"impls that are not considered to overlap may be considered to overlap in the future"##, - }, Lint { label: "conflicting_repr_hints", description: r##"conflicts between `#[repr(..)]` hints that were previously accepted and used in practice"##, @@ -86,10 +86,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "const_item_mutation", description: r##"detects attempts to mutate a `const` item"##, }, - Lint { - label: "const_patterns_without_partial_eq", - description: r##"constant in pattern does not implement `PartialEq`"##, - }, Lint { label: "dead_code", description: r##"detect unused, unexported items"## }, Lint { label: "deprecated", description: r##"detects use of deprecated items"## }, Lint { @@ -176,7 +172,7 @@ pub const DEFAULT_LINTS: &[Lint] = &[ }, Lint { label: "future_incompatible", - description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##, + description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, conflicting-repr-hints, const-evaluatable-unchecked, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety, writes-through-immutable-pointer"##, }, Lint { label: "fuzzy_provenance_casts", @@ -190,14 +186,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "ill_formed_attribute_input", description: r##"ill-formed attribute inputs that were previously accepted and used in practice"##, }, - Lint { - label: "illegal_floating_point_literal_pattern", - description: r##"floating-point literals cannot be used in patterns"##, - }, - Lint { - label: "implied_bounds_entailment", - description: r##"impl method assumes more implied bounds than its corresponding trait method"##, - }, Lint { label: "improper_ctypes", description: r##"proper use of libc types in foreign modules"##, @@ -372,6 +360,7 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "non_fmt_panics", description: r##"detect single-argument panic!() invocations in which the argument is not a format string"##, }, + Lint { label: "non_local_definitions", description: r##"checks for non-local definitions"## }, Lint { label: "non_shorthand_field_patterns", description: r##"using `Struct { x: x }` instead of `Struct { x }` in a pattern"##, @@ -388,10 +377,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "nonstandard_style", description: r##"lint group for: non-camel-case-types, non-snake-case, non-upper-case-globals"##, }, - Lint { - label: "nontrivial_structural_match", - description: r##"constant used in pattern of non-structural-match type and the constant's initializer expression contains values of non-structural-match types"##, - }, Lint { label: "noop_method_call", description: r##"detects the use of well-known noop methods"##, @@ -482,6 +467,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "rust_2021_prelude_collisions", description: r##"detects the usage of trait methods which are ambiguous with traits added to the prelude in future editions"##, }, + Lint { + label: "rust_2024_compatibility", + description: r##"lint group for: static-mut-refs, unsafe-op-in-unsafe-fn"##, + }, Lint { label: "semicolon_in_expressions_from_macros", description: r##"trailing semicolon in macro body used as expression"##, @@ -503,8 +492,8 @@ pub const DEFAULT_LINTS: &[Lint] = &[ description: r##"stable features found in `#[feature]` directive"##, }, Lint { - label: "suspicious_auto_trait_impls", - description: r##"the rules governing auto traits have recently changed resulting in potential breakage"##, + label: "static_mut_refs", + description: r##"shared references or mutable references of mutable static is discouraged"##, }, Lint { label: "suspicious_double_ref_op", @@ -579,6 +568,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ description: r##"enabling track_caller on an async fn is a no-op unless the async_fn_track_caller feature is enabled"##, }, Lint { label: "uninhabited_static", description: r##"uninhabited static"## }, + Lint { + label: "unit_bindings", + description: r##"binding is useless because it has the unit `()` type"##, + }, Lint { label: "unknown_crate_types", description: r##"unknown crate type found in `#[crate_type]` directive"##, @@ -610,10 +603,7 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "unsafe_op_in_unsafe_fn", description: r##"unsafe operations in unsafe functions without an explicit unsafe block are deprecated"##, }, - Lint { - label: "unstable_features", - description: r##"enabling unstable features (deprecated. do not use)"##, - }, + Lint { label: "unstable_features", description: r##"enabling unstable features"## }, Lint { label: "unstable_name_collisions", description: r##"detects name collision with an existing but unstable method"##, @@ -699,10 +689,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "unused_results", description: r##"unused result of an expression in a statement"##, }, - Lint { - label: "unused_tuple_struct_fields", - description: r##"detects tuple struct fields that are never read"##, - }, Lint { label: "unused_unsafe", description: r##"unnecessary use of an `unsafe` block"## }, Lint { label: "unused_variables", @@ -736,13 +722,17 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "while_true", description: r##"suggest using `loop { }` instead of `while true { }`"##, }, + Lint { + label: "writes_through_immutable_pointer", + description: r##"shared references are immutable, and pointers derived from them must not be written to"##, + }, ]; pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "future_incompatible", - description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##, + description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, conflicting-repr-hints, const-evaluatable-unchecked, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety, writes-through-immutable-pointer"##, }, children: &[ "deref_into_dyn_supertrait", @@ -751,16 +741,12 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ "byte_slice_in_packed_struct_with_derive", "cenum_impl_drop_cast", "coherence_leak_check", - "coinductive_overlap_in_coherence", "conflicting_repr_hints", "const_evaluatable_unchecked", - "const_patterns_without_partial_eq", "deprecated_cfg_attr_crate_type_name", "elided_lifetimes_in_associated_constant", "forbidden_lint_groups", "ill_formed_attribute_input", - "illegal_floating_point_literal_pattern", - "implied_bounds_entailment", "indirect_structural_match", "invalid_doc_attributes", "invalid_type_param_default", @@ -768,7 +754,6 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ "legacy_derive_helpers", "macro_expanded_macro_exports_accessed_by_absolute_paths", "missing_fragment_specifier", - "nontrivial_structural_match", "order_dependent_trait_objects", "patterns_in_fns_without_body", "pointer_structural_match", @@ -778,12 +763,12 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ "repr_transparent_external_private_fields", "semicolon_in_expressions_from_macros", "soft_unstable", - "suspicious_auto_trait_impls", "uninhabited_static", "unstable_name_collisions", "unstable_syntax_pre_expansion", "unsupported_calling_conventions", "where_clauses_object_safety", + "writes_through_immutable_pointer", ], }, LintGroup { @@ -841,6 +826,13 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ "non_fmt_panics", ], }, + LintGroup { + lint: Lint { + label: "rust_2024_compatibility", + description: r##"lint group for: static-mut-refs, unsafe-op-in-unsafe-fn"##, + }, + children: &["static_mut_refs", "unsafe_op_in_unsafe_fn"], + }, LintGroup { lint: Lint { label: "unused", @@ -1735,9 +1727,17 @@ The tracking issue for this feature is: [#110011] label: "async_fn_traits", description: r##"# `async_fn_traits` -This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +See Also: [`fn_traits`](../library-features/fn-traits.md) ------------------------- +---- + +The `async_fn_traits` feature allows for implementation of the [`AsyncFn*`] traits +for creating custom closure-like types that return futures. + +[`AsyncFn*`]: ../../std/ops/trait.AsyncFn.html + +The main difference to the `Fn*` family of traits is that `AsyncFn` can return a future +that borrows from itself (`FnOnce::Output` has no lifetime parameters, while `AsyncFn::CallFuture` does). "##, }, Lint { @@ -2377,17 +2377,6 @@ The tracking issue for this feature is: [#89653] [#89653]: https://github.com/rust-lang/rust/issues/89653 ------------------------- -"##, - }, - Lint { - label: "cfg_target_abi", - description: r##"# `cfg_target_abi` - -The tracking issue for this feature is: [#80970] - -[#80970]: https://github.com/rust-lang/rust/issues/80970 - ------------------------ "##, }, @@ -3133,6 +3122,17 @@ The tracking issue for this feature is: [#90603] This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +------------------------ +"##, + }, + Lint { + label: "const_intrinsic_copy", + description: r##"# `const_intrinsic_copy` + +The tracking issue for this feature is: [#80697] + +[#80697]: https://github.com/rust-lang/rust/issues/80697 + ------------------------ "##, }, @@ -3301,6 +3301,17 @@ The tracking issue for this feature is: [#110840] [#110840]: https://github.com/rust-lang/rust/issues/110840 +------------------------ +"##, + }, + Lint { + label: "const_ops", + description: r##"# `const_ops` + +The tracking issue for this feature is: [#90080] + +[#90080]: https://github.com/rust-lang/rust/issues/90080 + ------------------------ "##, }, @@ -3444,6 +3455,17 @@ The tracking issue for this feature is: [#80384] [#80384]: https://github.com/rust-lang/rust/issues/80384 +------------------------ +"##, + }, + Lint { + label: "const_refs_to_static", + description: r##"# `const_refs_to_static` + +The tracking issue for this feature is: [#119618] + +[#119618]: https://github.com/rust-lang/rust/issues/119618 + ------------------------ "##, }, @@ -4256,6 +4278,15 @@ The tracking issue for this feature is: [#27336] [#27336]: https://github.com/rust-lang/rust/issues/27336 +------------------------ +"##, + }, + Lint { + label: "delayed_debug_assertions", + description: r##"# `delayed_debug_assertions` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, }, @@ -4637,6 +4668,19 @@ The tracking issue for this feature is: [#57391] [#57391]: https://github.com/rust-lang/rust/issues/57391 ------------------------ +"##, + }, + Lint { + label: "duration_constructors", + description: r##"# `duration_constructors` + +The tracking issue for this feature is: [#120301] + +[#120301]: https://github.com/rust-lang/rust/issues/120301 + +------------------------ + +Add the methods `from_mins`, `from_hours` and `from_days` to `Duration`. "##, }, Lint { @@ -4647,6 +4691,17 @@ The tracking issue for this feature is: [#72440] [#72440]: https://github.com/rust-lang/rust/issues/72440 +------------------------ +"##, + }, + Lint { + label: "duration_units", + description: r##"# `duration_units` + +The tracking issue for this feature is: [#120301] + +[#120301]: https://github.com/rust-lang/rust/issues/120301 + ------------------------ "##, }, @@ -5659,13 +5714,62 @@ raw pointers in intra-doc links are unstable until it does. The tracking issue for this feature is: None. -Intrinsics are never intended to be stable directly, but intrinsics are often +Intrinsics are rarely intended to be stable directly, but are usually exported in some sort of stable manner. Prefer using the stable interfaces to the intrinsic directly when you can. ------------------------ +## Intrinsics with fallback logic + +Many intrinsics can be written in pure rust, albeit inefficiently or without supporting +some features that only exist on some backends. Backends can simply not implement those +intrinsics without causing any code miscompilations or failures to compile. +All intrinsic fallback bodies are automatically made cross-crate inlineable (like `#[inline]`) +by the codegen backend, but not the MIR inliner. + +```rust +#![feature(rustc_attrs, effects)] +#![allow(internal_features)] + +#[rustc_intrinsic] +const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} +``` + +Since these are just regular functions, it is perfectly ok to create the intrinsic twice: + +```rust +#![feature(rustc_attrs, effects)] +#![allow(internal_features)] + +#[rustc_intrinsic] +const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} + +mod foo { + #[rustc_intrinsic] + const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) { + panic!("noisy const dealloc") + } +} + +``` + +The behaviour on backends that override the intrinsic is exactly the same. On other +backends, the intrinsic behaviour depends on which implementation is called, just like +with any regular function. + +## Intrinsics lowered to MIR instructions + +Various intrinsics have native MIR operations that they correspond to. Instead of requiring +backends to implement both the intrinsic and the MIR operation, the `lower_intrinsics` pass +will convert the calls to the MIR operation. Backends do not need to know about these intrinsics +at all. + +## Intrinsics without fallback logic + +These must be implemented by all backends. + These are imported as if they were FFI functions, with the special `rust-intrinsic` ABI. For example, if one was in a freestanding context, but wished to be able to `transmute` between types, and @@ -5684,7 +5788,8 @@ extern "rust-intrinsic" { } ``` -As with any other FFI functions, these are always `unsafe` to call. +As with any other FFI functions, these are by default always `unsafe` to call. +You can add `#[rustc_safe_intrinsic]` to the intrinsic to make it safe to call. "##, }, Lint { @@ -5759,6 +5864,17 @@ The tracking issue for this feature is: [#101288] [#101288]: https://github.com/rust-lang/rust/issues/101288 +------------------------ +"##, + }, + Lint { + label: "is_riscv_feature_detected", + description: r##"# `is_riscv_feature_detected` + +The tracking issue for this feature is: [#111192] + +[#111192]: https://github.com/rust-lang/rust/issues/111192 + ------------------------ "##, }, @@ -5937,6 +6053,17 @@ The tracking issue for this feature is: [#87053] [#87053]: https://github.com/rust-lang/rust/issues/87053 +------------------------ +"##, + }, + Lint { + label: "lahfsahf_target_feature", + description: r##"# `lahfsahf_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + ------------------------ "##, }, @@ -6260,6 +6387,17 @@ The tracking issue for this feature is: [#82971] [#82971]: https://github.com/rust-lang/rust/issues/82971 +------------------------ +"##, + }, + Lint { + label: "local_waker", + description: r##"# `local_waker` + +The tracking issue for this feature is: [#118959] + +[#118959]: https://github.com/rust-lang/rust/issues/118959 + ------------------------ "##, }, @@ -6326,6 +6464,17 @@ The tracking issue for this feature is: [#82766] [#82766]: https://github.com/rust-lang/rust/issues/82766 +------------------------ +"##, + }, + Lint { + label: "mapped_lock_guards", + description: r##"# `mapped_lock_guards` + +The tracking issue for this feature is: [#117108] + +[#117108]: https://github.com/rust-lang/rust/issues/117108 + ------------------------ "##, }, @@ -6539,17 +6688,6 @@ The tracking issue for this feature is: [#83310] [#83310]: https://github.com/rust-lang/rust/issues/83310 ------------------------- -"##, - }, - Lint { - label: "mutex_unlock", - description: r##"# `mutex_unlock` - -The tracking issue for this feature is: [#81872] - -[#81872]: https://github.com/rust-lang/rust/issues/81872 - ------------------------ "##, }, @@ -6977,6 +7115,17 @@ The tracking issue for this feature is: [#70086] [#70086]: https://github.com/rust-lang/rust/issues/70086 +------------------------ +"##, + }, + Lint { + label: "os_str_display", + description: r##"# `os_str_display` + +The tracking issue for this feature is: [#120048] + +[#120048]: https://github.com/rust-lang/rust/issues/120048 + ------------------------ "##, }, @@ -7107,6 +7256,15 @@ The tracking issue for this feature is: [#27721] [#27721]: https://github.com/rust-lang/rust/issues/27721 +------------------------ +"##, + }, + Lint { + label: "pattern_complexity", + description: r##"# `pattern_complexity` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, }, @@ -7129,17 +7287,6 @@ The tracking issue for this feature is: [#86918] [#86918]: https://github.com/rust-lang/rust/issues/86918 ------------------------- -"##, - }, - Lint { - label: "platform_intrinsics", - description: r##"# `platform_intrinsics` - -The tracking issue for this feature is: [#27731] - -[#27731]: https://github.com/rust-lang/rust/issues/27731 - ------------------------ "##, }, @@ -7189,7 +7336,9 @@ The tracking issue for this feature is: [#44839] label: "prelude_2024", description: r##"# `prelude_2024` -This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +The tracking issue for this feature is: [#121042] + +[#121042]: https://github.com/rust-lang/rust/issues/121042 ------------------------ "##, @@ -7200,6 +7349,17 @@ This feature has no tracking issue, and is therefore likely internal to the comp This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +------------------------ +"##, + }, + Lint { + label: "prfchw_target_feature", + description: r##"# `prfchw_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + ------------------------ "##, }, @@ -7512,6 +7672,17 @@ The tracking issue for this feature is: [#101196] This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. +------------------------ +"##, + }, + Lint { + label: "reentrant_lock", + description: r##"# `reentrant_lock` + +The tracking issue for this feature is: [#121440] + +[#121440]: https://github.com/rust-lang/rust/issues/121440 + ------------------------ "##, }, @@ -8186,23 +8357,45 @@ This feature has no tracking issue, and is therefore likely internal to the comp "##, }, Lint { - label: "stdio_makes_pipe", - description: r##"# `stdio_makes_pipe` + label: "stdarch_arm_feature_detection", + description: r##"# `stdarch_arm_feature_detection` -The tracking issue for this feature is: [#98288] +The tracking issue for this feature is: [#111190] -[#98288]: https://github.com/rust-lang/rust/issues/98288 +[#111190]: https://github.com/rust-lang/rust/issues/111190 + +------------------------ +"##, + }, + Lint { + label: "stdarch_mips_feature_detection", + description: r##"# `stdarch_mips_feature_detection` + +The tracking issue for this feature is: [#111188] + +[#111188]: https://github.com/rust-lang/rust/issues/111188 + +------------------------ +"##, + }, + Lint { + label: "stdarch_powerpc_feature_detection", + description: r##"# `stdarch_powerpc_feature_detection` + +The tracking issue for this feature is: [#111191] + +[#111191]: https://github.com/rust-lang/rust/issues/111191 ------------------------ "##, }, Lint { - label: "stdsimd", - description: r##"# `stdsimd` + label: "stdio_makes_pipe", + description: r##"# `stdio_makes_pipe` -The tracking issue for this feature is: [#48556] +The tracking issue for this feature is: [#98288] -[#48556]: https://github.com/rust-lang/rust/issues/48556 +[#98288]: https://github.com/rust-lang/rust/issues/98288 ------------------------ "##, @@ -8464,6 +8657,17 @@ The tracking issue for this feature is: [#44839] [#44839]: https://github.com/rust-lang/rust/issues/44839 +------------------------ +"##, + }, + Lint { + label: "tcp_deferaccept", + description: r##"# `tcp_deferaccept` + +The tracking issue for this feature is: [#119639] + +[#119639]: https://github.com/rust-lang/rust/issues/119639 + ------------------------ "##, }, @@ -10156,7 +10360,7 @@ table: }, Lint { label: "clippy::blocks_in_conditions", - description: r##"Checks for `if` conditions that use blocks containing an + description: r##"Checks for `if` and `match` conditions that use blocks containing an expression, statements or conditions that use closures with blocks."##, }, Lint { @@ -10458,6 +10662,12 @@ See [RFC0212](https://github.com/rust-lang/rfcs/blob/master/text/0212-restore-in label: "clippy::deprecated_cfg_attr", description: r##"Checks for `#[cfg_attr(rustfmt, rustfmt_skip)]` and suggests to replace it with `#[rustfmt::skip]`."##, + }, + Lint { + label: "clippy::deprecated_clippy_cfg_attr", + description: r##"Checks for `#[cfg_attr(feature = cargo-clippy, ...)]` and for +`#[cfg(feature = cargo-clippy)]` and suggests to replace it with +`#[cfg_attr(clippy, ...)]` or `#[cfg(clippy)]`."##, }, Lint { label: "clippy::deprecated_semver", @@ -10601,6 +10811,7 @@ eagerly (e.g. using `bool::then_some`)."##, description: r##"Checks for usage of if expressions with an `else if` branch, but without a final `else` branch."##, }, + Lint { label: "clippy::empty_docs", description: r##"Detects documentation that is empty."## }, Lint { label: "clippy::empty_drop", description: r##"Checks for empty `Drop` implementations."##, @@ -11357,6 +11568,7 @@ cannot be represented as the underlying type without loss."##, description: r##"Checks for usage of `std::mem::size_of::() * 8` when `T::BITS` is available."##, }, + Lint { label: "clippy::manual_c_str_literals", description: r##""## }, Lint { label: "clippy::manual_clamp", description: r##"Identifies good opportunities for a clamp function from std or core, and suggests using it."##, @@ -11731,6 +11943,10 @@ rather than globally."##, label: "clippy::mistyped_literal_suffixes", description: r##"Warns for mistyped suffix in literals"##, }, + Lint { + label: "clippy::mixed_attributes_style", + description: r##"Checks that an item has only one kind of attributes."##, + }, Lint { label: "clippy::mixed_case_hex_literals", description: r##"Warns on hexadecimal literals with mixed-case letter @@ -11763,6 +11979,10 @@ containing module's name."##, one."##, }, Lint { label: "clippy::multi_assignments", description: r##"Checks for nested assignments."## }, + Lint { + label: "clippy::multiple_bound_locations", + description: r##"Check if a generic is defined both in the bound predicate and in the `where` clause."##, + }, Lint { label: "clippy::multiple_crate_versions", description: r##"Checks to see if multiple versions of a crate are being @@ -12336,8 +12556,8 @@ in `vec![elem; len]`"##, Lint { label: "clippy::read_line_without_trim", description: r##"Looks for calls to [`Stdin::read_line`] to read a line from the standard input -into a string, then later attempting to parse this string into a type without first trimming it, which will -always fail because the string has a trailing newline in it."##, +into a string, then later attempting to use that string for an operation that will never +work for strings with a trailing newline character in it (e.g. parsing into a `i32`)."##, }, Lint { label: "clippy::read_zero_byte_vec", @@ -12444,6 +12664,11 @@ do not change the type."##, label: "clippy::redundant_type_annotations", description: r##"Warns about needless / redundant type annotations."##, }, + Lint { + label: "clippy::ref_as_ptr", + description: r##"Checks for casts of references to pointer using `as` +and suggests `std::ptr::from_ref` and `std::ptr::from_mut` instead."##, + }, Lint { label: "clippy::ref_binding_to_reference", description: r##"Checks for `ref` bindings which create a reference to a reference."##, @@ -13095,6 +13320,11 @@ as returning a large `T` directly may be detrimental to performance."##, label: "clippy::unnecessary_cast", description: r##"Checks for casts to the same type, casts of int literals to integer types, casts of float literals to float types and casts between raw pointers without changing type or constness."##, + }, + Lint { + label: "clippy::unnecessary_clippy_cfg", + description: r##"Checks for `#[cfg_attr(clippy, allow(clippy::lint))]` +and suggests to replace it with `#[allow(clippy::lint)]`."##, }, Lint { label: "clippy::unnecessary_fallible_conversions", @@ -13119,6 +13349,10 @@ find or map operations and suggests the appropriate option."##, Specifically, this checks for `fold`s which could be replaced by `any`, `all`, `sum` or `product`."##, }, + Lint { + label: "clippy::unnecessary_get_then_check", + description: r##"Checks the usage of `.get().is_some()` or `.get().is_none()` on std map types."##, + }, Lint { label: "clippy::unnecessary_join", description: r##"Checks for usage of `.collect::>().join()` on iterators."##, @@ -13830,7 +14064,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::pedantic", - description: r##"lint group for: clippy::bool_to_int_with_if, clippy::borrow_as_ptr, clippy::case_sensitive_file_extension_comparisons, clippy::cast_lossless, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_precision_loss, clippy::cast_ptr_alignment, clippy::cast_sign_loss, clippy::checked_conversions, clippy::cloned_instead_of_copied, clippy::copy_iterator, clippy::default_trait_access, clippy::doc_link_with_quotes, clippy::doc_markdown, clippy::empty_enum, clippy::enum_glob_use, clippy::expl_impl_clone_on_copy, clippy::explicit_deref_methods, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::flat_map_option, clippy::float_cmp, clippy::fn_params_excessive_bools, clippy::from_iter_instead_of_collect, clippy::if_not_else, clippy::ignored_unit_patterns, clippy::implicit_clone, clippy::implicit_hasher, clippy::inconsistent_struct_constructor, clippy::index_refutable_slice, clippy::inefficient_to_string, clippy::inline_always, clippy::into_iter_without_iter, clippy::invalid_upcast_comparisons, clippy::items_after_statements, clippy::iter_filter_is_ok, clippy::iter_filter_is_some, clippy::iter_not_returning_iterator, clippy::iter_without_into_iter, clippy::large_digit_groups, clippy::large_futures, clippy::large_stack_arrays, clippy::large_types_passed_by_value, clippy::linkedlist, clippy::macro_use_imports, clippy::manual_assert, clippy::manual_instant_elapsed, clippy::manual_is_variant_and, clippy::manual_let_else, clippy::manual_ok_or, clippy::manual_string_new, clippy::many_single_char_names, clippy::map_unwrap_or, clippy::match_bool, clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wild_err_arm, clippy::match_wildcard_for_single_variants, clippy::maybe_infinite_iter, clippy::mismatching_type_param_order, clippy::missing_errors_doc, clippy::missing_fields_in_debug, clippy::missing_panics_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::mut_mut, clippy::naive_bytecount, clippy::needless_bitwise_bool, clippy::needless_continue, clippy::needless_for_each, clippy::needless_pass_by_value, clippy::needless_raw_string_hashes, clippy::no_effect_underscore_binding, clippy::no_mangle_with_rust_abi, clippy::option_as_ref_cloned, clippy::option_option, clippy::ptr_as_ptr, clippy::ptr_cast_constness, clippy::pub_underscore_fields, clippy::range_minus_one, clippy::range_plus_one, clippy::redundant_closure_for_method_calls, clippy::redundant_else, clippy::ref_binding_to_reference, clippy::ref_option_ref, clippy::return_self_not_must_use, clippy::same_functions_in_if_condition, clippy::semicolon_if_nothing_returned, clippy::should_panic_without_expect, clippy::similar_names, clippy::single_match_else, clippy::stable_sort_primitive, clippy::str_split_at_newline, clippy::string_add_assign, clippy::struct_excessive_bools, clippy::struct_field_names, clippy::too_many_lines, clippy::transmute_ptr_to_ptr, clippy::trivially_copy_pass_by_ref, clippy::unchecked_duration_subtraction, clippy::unicode_not_nfc, clippy::uninlined_format_args, clippy::unnecessary_box_returns, clippy::unnecessary_join, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::unreadable_literal, clippy::unsafe_derive_deserialize, clippy::unused_async, clippy::unused_self, clippy::used_underscore_binding, clippy::verbose_bit_mask, clippy::wildcard_imports, clippy::zero_sized_map_values"##, + description: r##"lint group for: clippy::bool_to_int_with_if, clippy::borrow_as_ptr, clippy::case_sensitive_file_extension_comparisons, clippy::cast_lossless, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_precision_loss, clippy::cast_ptr_alignment, clippy::cast_sign_loss, clippy::checked_conversions, clippy::cloned_instead_of_copied, clippy::copy_iterator, clippy::default_trait_access, clippy::doc_link_with_quotes, clippy::doc_markdown, clippy::empty_enum, clippy::enum_glob_use, clippy::expl_impl_clone_on_copy, clippy::explicit_deref_methods, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::flat_map_option, clippy::float_cmp, clippy::fn_params_excessive_bools, clippy::from_iter_instead_of_collect, clippy::if_not_else, clippy::ignored_unit_patterns, clippy::implicit_clone, clippy::implicit_hasher, clippy::inconsistent_struct_constructor, clippy::index_refutable_slice, clippy::inefficient_to_string, clippy::inline_always, clippy::into_iter_without_iter, clippy::invalid_upcast_comparisons, clippy::items_after_statements, clippy::iter_filter_is_ok, clippy::iter_filter_is_some, clippy::iter_not_returning_iterator, clippy::iter_without_into_iter, clippy::large_digit_groups, clippy::large_futures, clippy::large_stack_arrays, clippy::large_types_passed_by_value, clippy::linkedlist, clippy::macro_use_imports, clippy::manual_assert, clippy::manual_c_str_literals, clippy::manual_instant_elapsed, clippy::manual_is_variant_and, clippy::manual_let_else, clippy::manual_ok_or, clippy::manual_string_new, clippy::many_single_char_names, clippy::map_unwrap_or, clippy::match_bool, clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wild_err_arm, clippy::match_wildcard_for_single_variants, clippy::maybe_infinite_iter, clippy::mismatching_type_param_order, clippy::missing_errors_doc, clippy::missing_fields_in_debug, clippy::missing_panics_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::mut_mut, clippy::naive_bytecount, clippy::needless_bitwise_bool, clippy::needless_continue, clippy::needless_for_each, clippy::needless_pass_by_value, clippy::needless_raw_string_hashes, clippy::no_effect_underscore_binding, clippy::no_mangle_with_rust_abi, clippy::option_as_ref_cloned, clippy::option_option, clippy::ptr_as_ptr, clippy::ptr_cast_constness, clippy::pub_underscore_fields, clippy::range_minus_one, clippy::range_plus_one, clippy::redundant_closure_for_method_calls, clippy::redundant_else, clippy::ref_as_ptr, clippy::ref_binding_to_reference, clippy::ref_option_ref, clippy::return_self_not_must_use, clippy::same_functions_in_if_condition, clippy::semicolon_if_nothing_returned, clippy::should_panic_without_expect, clippy::similar_names, clippy::single_match_else, clippy::stable_sort_primitive, clippy::str_split_at_newline, clippy::string_add_assign, clippy::struct_excessive_bools, clippy::struct_field_names, clippy::too_many_lines, clippy::transmute_ptr_to_ptr, clippy::trivially_copy_pass_by_ref, clippy::unchecked_duration_subtraction, clippy::unicode_not_nfc, clippy::uninlined_format_args, clippy::unnecessary_box_returns, clippy::unnecessary_join, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::unreadable_literal, clippy::unsafe_derive_deserialize, clippy::unused_async, clippy::unused_self, clippy::used_underscore_binding, clippy::verbose_bit_mask, clippy::wildcard_imports, clippy::zero_sized_map_values"##, }, children: &[ "clippy::bool_to_int_with_if", @@ -13881,6 +14115,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::linkedlist", "clippy::macro_use_imports", "clippy::manual_assert", + "clippy::manual_c_str_literals", "clippy::manual_instant_elapsed", "clippy::manual_is_variant_and", "clippy::manual_let_else", @@ -13918,6 +14153,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::range_plus_one", "clippy::redundant_closure_for_method_calls", "clippy::redundant_else", + "clippy::ref_as_ptr", "clippy::ref_binding_to_reference", "clippy::ref_option_ref", "clippy::return_self_not_must_use", @@ -14262,7 +14498,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::suspicious", - description: r##"lint group for: clippy::almost_complete_range, clippy::arc_with_non_send_sync, clippy::await_holding_invalid_type, clippy::await_holding_lock, clippy::await_holding_refcell_ref, clippy::blanket_clippy_restriction_lints, clippy::cast_abs_to_unsigned, clippy::cast_enum_constructor, clippy::cast_enum_truncation, clippy::cast_nan_to_int, clippy::cast_slice_from_raw_parts, clippy::crate_in_macro_def, clippy::drop_non_drop, clippy::duplicate_mod, clippy::empty_loop, clippy::float_equality_without_abs, clippy::forget_non_drop, clippy::four_forward_slashes, clippy::from_raw_with_void_ptr, clippy::incompatible_msrv, clippy::ineffective_open_options, clippy::iter_out_of_bounds, clippy::join_absolute_paths, clippy::let_underscore_future, clippy::lines_filter_map_ok, clippy::maybe_misused_cfg, clippy::misnamed_getters, clippy::misrefactored_assign_op, clippy::multi_assignments, clippy::mut_range_bound, clippy::mutable_key_type, clippy::no_effect_replace, clippy::non_canonical_clone_impl, clippy::non_canonical_partial_ord_impl, clippy::octal_escapes, clippy::path_ends_with_ext, clippy::permissions_set_readonly_false, clippy::print_in_format_impl, clippy::rc_clone_in_vec_init, clippy::repeat_vec_with_capacity, clippy::single_range_in_vec_init, clippy::size_of_ref, clippy::suspicious_arithmetic_impl, clippy::suspicious_assignment_formatting, clippy::suspicious_command_arg_space, clippy::suspicious_doc_comments, clippy::suspicious_else_formatting, clippy::suspicious_map, clippy::suspicious_op_assign_impl, clippy::suspicious_open_options, clippy::suspicious_to_owned, clippy::suspicious_unary_op_formatting, clippy::swap_ptr_to_ref, clippy::test_attr_in_doctest, clippy::type_id_on_box, clippy::unconditional_recursion, clippy::unnecessary_result_map_or_else"##, + description: r##"lint group for: clippy::almost_complete_range, clippy::arc_with_non_send_sync, clippy::await_holding_invalid_type, clippy::await_holding_lock, clippy::await_holding_refcell_ref, clippy::blanket_clippy_restriction_lints, clippy::cast_abs_to_unsigned, clippy::cast_enum_constructor, clippy::cast_enum_truncation, clippy::cast_nan_to_int, clippy::cast_slice_from_raw_parts, clippy::crate_in_macro_def, clippy::deprecated_clippy_cfg_attr, clippy::drop_non_drop, clippy::duplicate_mod, clippy::empty_docs, clippy::empty_loop, clippy::float_equality_without_abs, clippy::forget_non_drop, clippy::four_forward_slashes, clippy::from_raw_with_void_ptr, clippy::incompatible_msrv, clippy::ineffective_open_options, clippy::iter_out_of_bounds, clippy::join_absolute_paths, clippy::let_underscore_future, clippy::lines_filter_map_ok, clippy::maybe_misused_cfg, clippy::misnamed_getters, clippy::misrefactored_assign_op, clippy::mixed_attributes_style, clippy::multi_assignments, clippy::multiple_bound_locations, clippy::mut_range_bound, clippy::mutable_key_type, clippy::no_effect_replace, clippy::non_canonical_clone_impl, clippy::non_canonical_partial_ord_impl, clippy::octal_escapes, clippy::path_ends_with_ext, clippy::permissions_set_readonly_false, clippy::print_in_format_impl, clippy::rc_clone_in_vec_init, clippy::repeat_vec_with_capacity, clippy::single_range_in_vec_init, clippy::size_of_ref, clippy::suspicious_arithmetic_impl, clippy::suspicious_assignment_formatting, clippy::suspicious_command_arg_space, clippy::suspicious_doc_comments, clippy::suspicious_else_formatting, clippy::suspicious_map, clippy::suspicious_op_assign_impl, clippy::suspicious_open_options, clippy::suspicious_to_owned, clippy::suspicious_unary_op_formatting, clippy::swap_ptr_to_ref, clippy::test_attr_in_doctest, clippy::type_id_on_box, clippy::unconditional_recursion, clippy::unnecessary_clippy_cfg, clippy::unnecessary_get_then_check, clippy::unnecessary_result_map_or_else"##, }, children: &[ "clippy::almost_complete_range", @@ -14277,8 +14513,10 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::cast_nan_to_int", "clippy::cast_slice_from_raw_parts", "clippy::crate_in_macro_def", + "clippy::deprecated_clippy_cfg_attr", "clippy::drop_non_drop", "clippy::duplicate_mod", + "clippy::empty_docs", "clippy::empty_loop", "clippy::float_equality_without_abs", "clippy::forget_non_drop", @@ -14293,7 +14531,9 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::maybe_misused_cfg", "clippy::misnamed_getters", "clippy::misrefactored_assign_op", + "clippy::mixed_attributes_style", "clippy::multi_assignments", + "clippy::multiple_bound_locations", "clippy::mut_range_bound", "clippy::mutable_key_type", "clippy::no_effect_replace", @@ -14321,6 +14561,8 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::test_attr_in_doctest", "clippy::type_id_on_box", "clippy::unconditional_recursion", + "clippy::unnecessary_clippy_cfg", + "clippy::unnecessary_get_then_check", "clippy::unnecessary_result_map_or_else", ], }, diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 3411133f50e3..e63717e35a3b 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -5434,13 +5434,62 @@ fn hover_feature() { The tracking issue for this feature is: None. - Intrinsics are never intended to be stable directly, but intrinsics are often + Intrinsics are rarely intended to be stable directly, but are usually exported in some sort of stable manner. Prefer using the stable interfaces to the intrinsic directly when you can. ------------------------ + ## Intrinsics with fallback logic + + Many intrinsics can be written in pure rust, albeit inefficiently or without supporting + some features that only exist on some backends. Backends can simply not implement those + intrinsics without causing any code miscompilations or failures to compile. + All intrinsic fallback bodies are automatically made cross-crate inlineable (like `#[inline]`) + by the codegen backend, but not the MIR inliner. + + ```rust + #![feature(rustc_attrs, effects)] + #![allow(internal_features)] + + #[rustc_intrinsic] + const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} + ``` + + Since these are just regular functions, it is perfectly ok to create the intrinsic twice: + + ```rust + #![feature(rustc_attrs, effects)] + #![allow(internal_features)] + + #[rustc_intrinsic] + const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} + + mod foo { + #[rustc_intrinsic] + const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) { + panic!("noisy const dealloc") + } + } + + ``` + + The behaviour on backends that override the intrinsic is exactly the same. On other + backends, the intrinsic behaviour depends on which implementation is called, just like + with any regular function. + + ## Intrinsics lowered to MIR instructions + + Various intrinsics have native MIR operations that they correspond to. Instead of requiring + backends to implement both the intrinsic and the MIR operation, the `lower_intrinsics` pass + will convert the calls to the MIR operation. Backends do not need to know about these intrinsics + at all. + + ## Intrinsics without fallback logic + + These must be implemented by all backends. + These are imported as if they were FFI functions, with the special `rust-intrinsic` ABI. For example, if one was in a freestanding context, but wished to be able to `transmute` between types, and @@ -5459,7 +5508,8 @@ fn hover_feature() { } ``` - As with any other FFI functions, these are always `unsafe` to call. + As with any other FFI functions, these are by default always `unsafe` to call. + You can add `#[rustc_safe_intrinsic]` to the intrinsic to make it safe to call. "#]], ) From ac641a19e7da1df98a95a9c4b7d57df2208d1722 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 21:40:57 +0000 Subject: [PATCH 27/69] Bump mio from 0.8.5 to 0.8.11 Bumps [mio](https://github.com/tokio-rs/mio) from 0.8.5 to 0.8.11. - [Release notes](https://github.com/tokio-rs/mio/releases) - [Changelog](https://github.com/tokio-rs/mio/blob/master/CHANGELOG.md) - [Commits](https://github.com/tokio-rs/mio/compare/v0.8.5...v0.8.11) --- updated-dependencies: - dependency-name: mio dependency-type: indirect ... Signed-off-by: dependabot[bot] --- Cargo.lock | 91 ++++++++++-------------------------------------------- 1 file changed, 17 insertions(+), 74 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 89a1f68cce0f..3667dec23a6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -296,7 +296,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf" dependencies = [ "nix 0.27.1", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -390,7 +390,7 @@ dependencies = [ "cfg-if", "libc", "redox_syscall 0.3.5", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -622,7 +622,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -891,7 +891,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb" dependencies = [ "cfg-if", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -1073,14 +1073,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.5" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", "wasi", - "windows-sys 0.42.0", + "windows-sys", ] [[package]] @@ -1089,7 +1089,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "359f76430b20a79f9e20e115b3428614e654f04fab314482fc0fda0ebd3c6044" dependencies = [ - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -1137,7 +1137,7 @@ dependencies = [ "log", "mio", "walkdir", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -1146,7 +1146,7 @@ version = "0.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c073d3c1930d0751774acf49e66653acecb416c3a54c6ec095a9b11caddb5a68" dependencies = [ - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -2325,21 +2325,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -2355,93 +2340,51 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.48.0" From 2a4ba4295b3bb53e672cb2dded2247a5553cf089 Mon Sep 17 00:00:00 2001 From: Niklas Lindorfer Date: Mon, 4 Mar 2024 18:14:25 +0000 Subject: [PATCH 28/69] fix: hide destructure_struct_binding assist if no public fields --- .../handlers/destructure_struct_binding.rs | 27 +++++++++++++------ crates/syntax/src/ast/make.rs | 5 +++- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/crates/ide-assists/src/handlers/destructure_struct_binding.rs b/crates/ide-assists/src/handlers/destructure_struct_binding.rs index 4edc52b614ab..c1a3f9302650 100644 --- a/crates/ide-assists/src/handlers/destructure_struct_binding.rs +++ b/crates/ide-assists/src/handlers/destructure_struct_binding.rs @@ -107,6 +107,10 @@ fn collect_data(ident_pat: ast::IdentPat, ctx: &AssistContext<'_>) -> Option ast::RecordPatFieldList { let mut fields = fields.into_iter().join(", "); if let Some(rest_pat) = rest_pat { - format_to!(fields, ", {rest_pat}"); + if !fields.is_empty() { + fields.push_str(", "); + } + format_to!(fields, "{rest_pat}"); } ast_from_text(&format!("fn f(S {{ {fields} }}: ()))")) } From fe0daa7be3437766ac70422fb9df8c20523fd64a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 5 Mar 2024 09:37:25 +0100 Subject: [PATCH 29/69] Revert "prioritise rustup sysroots over system ones" This reverts commit 9f1d4aa4b9e4a1572c1210b3bd7c7490778b6112. --- crates/toolchain/src/lib.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/toolchain/src/lib.rs b/crates/toolchain/src/lib.rs index 793138588a3f..ae71b6700c0b 100644 --- a/crates/toolchain/src/lib.rs +++ b/crates/toolchain/src/lib.rs @@ -63,17 +63,21 @@ fn get_path_for_executable(executable_name: &'static str) -> PathBuf { // The current implementation checks three places for an executable to use: // 1) Appropriate environment variable (erroring if this is set but not a usable executable) // example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc - // 2) `$CARGO_HOME/bin/` + // 2) `` + // example: for cargo, this tries just `cargo`, which will succeed if `cargo` is on the $PATH + // 3) `$CARGO_HOME/bin/` // where $CARGO_HOME defaults to ~/.cargo (see https://doc.rust-lang.org/cargo/guide/cargo-home.html) // example: for cargo, this tries $CARGO_HOME/bin/cargo, or ~/.cargo/bin/cargo if $CARGO_HOME is unset. // It seems that this is a reasonable place to try for cargo, rustc, and rustup - // 3) `` - // example: for cargo, this tries just `cargo`, which will succeed if `cargo` is on the $PATH let env_var = executable_name.to_ascii_uppercase(); if let Some(path) = env::var_os(env_var) { return path.into(); } + if lookup_in_path(executable_name) { + return executable_name.into(); + } + if let Some(mut path) = get_cargo_home() { path.push("bin"); path.push(executable_name); @@ -82,10 +86,6 @@ fn get_path_for_executable(executable_name: &'static str) -> PathBuf { } } - if lookup_in_path(executable_name) { - return executable_name.into(); - } - executable_name.into() } From c310aee8d670c4436ef2e1a8bdf8727cf8abbfac Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 5 Mar 2024 10:16:30 +0100 Subject: [PATCH 30/69] For toolchain binaries ue the full path found in $PATH --- Cargo.lock | 1 - crates/ide/src/expand_macro.rs | 2 +- .../proc-macro-srv/proc-macro-test/Cargo.toml | 3 - .../proc-macro-srv/proc-macro-test/build.rs | 14 +-- crates/project-model/src/sysroot.rs | 6 +- crates/rust-analyzer/src/handlers/request.rs | 2 +- crates/toolchain/src/lib.rs | 102 +++++++++--------- 7 files changed, 63 insertions(+), 67 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3667dec23a6f..c6df491596ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1336,7 +1336,6 @@ name = "proc-macro-test" version = "0.0.0" dependencies = [ "cargo_metadata", - "toolchain", ] [[package]] diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs index 9eb5a9db6250..4b0961cbbeba 100644 --- a/crates/ide/src/expand_macro.rs +++ b/crates/ide/src/expand_macro.rs @@ -189,7 +189,7 @@ fn _format( let &crate_id = db.relevant_crates(file_id).iter().next()?; let edition = db.crate_graph()[crate_id].edition; - let mut cmd = std::process::Command::new(toolchain::rustfmt()); + let mut cmd = std::process::Command::new(toolchain::Tool::Rustfmt.path()); cmd.arg("--edition"); cmd.arg(edition.to_string()); diff --git a/crates/proc-macro-srv/proc-macro-test/Cargo.toml b/crates/proc-macro-srv/proc-macro-test/Cargo.toml index 7977afb1cbd2..7c6a1ba46b5f 100644 --- a/crates/proc-macro-srv/proc-macro-test/Cargo.toml +++ b/crates/proc-macro-srv/proc-macro-test/Cargo.toml @@ -11,6 +11,3 @@ doctest = false [build-dependencies] cargo_metadata = "0.18.1" - -# local deps -toolchain.workspace = true diff --git a/crates/proc-macro-srv/proc-macro-test/build.rs b/crates/proc-macro-srv/proc-macro-test/build.rs index ff62980e4ffe..c76c201d69e8 100644 --- a/crates/proc-macro-srv/proc-macro-test/build.rs +++ b/crates/proc-macro-srv/proc-macro-test/build.rs @@ -18,12 +18,12 @@ use cargo_metadata::Message; fn main() { println!("cargo:rerun-if-changed=imp"); + let cargo = env::var_os("CARGO").unwrap_or_else(|| "cargo".into()); + let has_features = env::var_os("RUSTC_BOOTSTRAP").is_some() - || String::from_utf8( - Command::new(toolchain::cargo()).arg("--version").output().unwrap().stdout, - ) - .unwrap() - .contains("nightly"); + || String::from_utf8(Command::new(&cargo).arg("--version").output().unwrap().stdout) + .unwrap() + .contains("nightly"); let out_dir = env::var_os("OUT_DIR").unwrap(); let out_dir = Path::new(&out_dir); @@ -66,7 +66,7 @@ fn main() { let target_dir = out_dir.join("target"); - let mut cmd = Command::new(toolchain::cargo()); + let mut cmd = Command::new(&cargo); cmd.current_dir(&staging_dir) .args(["build", "-p", "proc-macro-test-impl", "--message-format", "json"]) // Explicit override the target directory to avoid using the same one which the parent @@ -96,7 +96,7 @@ fn main() { let repr = format!("{name} {version}"); // New Package Id Spec since rust-lang/cargo#13311 let pkgid = String::from_utf8( - Command::new(toolchain::cargo()) + Command::new(cargo) .current_dir(&staging_dir) .args(["pkgid", name]) .output() diff --git a/crates/project-model/src/sysroot.rs b/crates/project-model/src/sysroot.rs index ea24393ed8a2..a486a38510a8 100644 --- a/crates/project-model/src/sysroot.rs +++ b/crates/project-model/src/sysroot.rs @@ -12,7 +12,7 @@ use itertools::Itertools; use la_arena::{Arena, Idx}; use paths::{AbsPath, AbsPathBuf}; use rustc_hash::FxHashMap; -use toolchain::probe_for_binary; +use toolchain::{probe_for_binary, Tool}; use crate::{utf8_stdout, CargoConfig, CargoWorkspace, ManifestPath}; @@ -411,7 +411,7 @@ fn discover_sysroot_dir( current_dir: &AbsPath, extra_env: &FxHashMap, ) -> Result { - let mut rustc = Command::new(toolchain::rustc()); + let mut rustc = Command::new(Tool::Rustc.path()); rustc.envs(extra_env); rustc.current_dir(current_dir).args(["--print", "sysroot"]); tracing::debug!("Discovering sysroot by {:?}", rustc); @@ -443,7 +443,7 @@ fn discover_sysroot_src_dir_or_add_component( ) -> Result { discover_sysroot_src_dir(sysroot_path) .or_else(|| { - let mut rustup = Command::new(toolchain::rustup()); + let mut rustup = Command::new(Tool::Rustup.prefer_proxy()); rustup.envs(extra_env); rustup.current_dir(current_dir).args(["component", "add", "rust-src"]); tracing::info!("adding rust-src component by {:?}", rustup); diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index 0e005975fbae..091f485db006 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -1937,7 +1937,7 @@ fn run_rustfmt( let mut command = match snap.config.rustfmt() { RustfmtConfig::Rustfmt { extra_args, enable_range_formatting } => { // FIXME: Set RUSTUP_TOOLCHAIN - let mut cmd = process::Command::new(toolchain::rustfmt()); + let mut cmd = process::Command::new(toolchain::Tool::Rustfmt.path()); cmd.envs(snap.config.extra_env()); cmd.args(extra_args); diff --git a/crates/toolchain/src/lib.rs b/crates/toolchain/src/lib.rs index ae71b6700c0b..e65a060672ee 100644 --- a/crates/toolchain/src/lib.rs +++ b/crates/toolchain/src/lib.rs @@ -16,8 +16,42 @@ pub enum Tool { } impl Tool { + pub fn proxy(self) -> Option { + cargo_proxy(self.name()) + } + + /// Return a `PathBuf` to use for the given executable. + /// + /// The current implementation checks three places for an executable to use: + /// 1) `$CARGO_HOME/bin/` + /// where $CARGO_HOME defaults to ~/.cargo (see https://doc.rust-lang.org/cargo/guide/cargo-home.html) + /// example: for cargo, this tries $CARGO_HOME/bin/cargo, or ~/.cargo/bin/cargo if $CARGO_HOME is unset. + /// It seems that this is a reasonable place to try for cargo, rustc, and rustup + /// 2) Appropriate environment variable (erroring if this is set but not a usable executable) + /// example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc + /// 3) $PATH/`` + /// example: for cargo, this tries all paths in $PATH with appended `cargo`, returning the + /// first that exists + /// 4) If all else fails, we just try to use the executable name directly + pub fn prefer_proxy(self) -> PathBuf { + invoke(&[cargo_proxy, lookup_as_env_var, lookup_in_path], self.name()) + } + + /// Return a `PathBuf` to use for the given executable. + /// + /// The current implementation checks three places for an executable to use: + /// 1) Appropriate environment variable (erroring if this is set but not a usable executable) + /// example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc + /// 2) $PATH/`` + /// example: for cargo, this tries all paths in $PATH with appended `cargo`, returning the + /// first that exists + /// 3) `$CARGO_HOME/bin/` + /// where $CARGO_HOME defaults to ~/.cargo (see https://doc.rust-lang.org/cargo/guide/cargo-home.html) + /// example: for cargo, this tries $CARGO_HOME/bin/cargo, or ~/.cargo/bin/cargo if $CARGO_HOME is unset. + /// It seems that this is a reasonable place to try for cargo, rustc, and rustup + /// 4) If all else fails, we just try to use the executable name directly pub fn path(self) -> PathBuf { - get_path_for_executable(self.name()) + invoke(&[lookup_as_env_var, lookup_in_path, cargo_proxy], self.name()) } pub fn path_in(self, path: &Path) -> Option { @@ -38,60 +72,21 @@ impl Tool { } } -pub fn cargo() -> PathBuf { - get_path_for_executable("cargo") -} - -pub fn rustc() -> PathBuf { - get_path_for_executable("rustc") +fn invoke(list: &[fn(&str) -> Option], executable: &str) -> PathBuf { + list.iter().find_map(|it| it(executable)).unwrap_or_else(|| executable.into()) } -pub fn rustup() -> PathBuf { - get_path_for_executable("rustup") +/// Looks up the binary as its SCREAMING upper case in the env variables. +fn lookup_as_env_var(executable_name: &str) -> Option { + env::var_os(executable_name.to_ascii_uppercase()).map(Into::into) } -pub fn rustfmt() -> PathBuf { - get_path_for_executable("rustfmt") -} - -/// Return a `PathBuf` to use for the given executable. -/// -/// E.g., `get_path_for_executable("cargo")` may return just `cargo` if that -/// gives a valid Cargo executable; or it may return a full path to a valid -/// Cargo. -fn get_path_for_executable(executable_name: &'static str) -> PathBuf { - // The current implementation checks three places for an executable to use: - // 1) Appropriate environment variable (erroring if this is set but not a usable executable) - // example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc - // 2) `` - // example: for cargo, this tries just `cargo`, which will succeed if `cargo` is on the $PATH - // 3) `$CARGO_HOME/bin/` - // where $CARGO_HOME defaults to ~/.cargo (see https://doc.rust-lang.org/cargo/guide/cargo-home.html) - // example: for cargo, this tries $CARGO_HOME/bin/cargo, or ~/.cargo/bin/cargo if $CARGO_HOME is unset. - // It seems that this is a reasonable place to try for cargo, rustc, and rustup - let env_var = executable_name.to_ascii_uppercase(); - if let Some(path) = env::var_os(env_var) { - return path.into(); - } - - if lookup_in_path(executable_name) { - return executable_name.into(); - } - - if let Some(mut path) = get_cargo_home() { - path.push("bin"); - path.push(executable_name); - if let Some(path) = probe_for_binary(path) { - return path; - } - } - - executable_name.into() -} - -fn lookup_in_path(exec: &str) -> bool { - let paths = env::var_os("PATH").unwrap_or_default(); - env::split_paths(&paths).map(|path| path.join(exec)).find_map(probe_for_binary).is_some() +/// Looks up the binary in the cargo home directory if it exists. +fn cargo_proxy(executable_name: &str) -> Option { + let mut path = get_cargo_home()?; + path.push("bin"); + path.push(executable_name); + probe_for_binary(path) } fn get_cargo_home() -> Option { @@ -107,6 +102,11 @@ fn get_cargo_home() -> Option { None } +fn lookup_in_path(exec: &str) -> Option { + let paths = env::var_os("PATH").unwrap_or_default(); + env::split_paths(&paths).map(|path| path.join(exec)).find_map(probe_for_binary) +} + pub fn probe_for_binary(path: PathBuf) -> Option { let with_extension = match env::consts::EXE_EXTENSION { "" => None, From 6b48133e9acd360004f4a193238ba493d18bf921 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 5 Mar 2024 10:44:17 +0100 Subject: [PATCH 31/69] Prefer cargo proxies when setting RUSTUP_TOOLCHAIN --- crates/project-model/src/build_scripts.rs | 8 ++-- crates/project-model/src/cargo_workspace.rs | 17 ++++---- crates/project-model/src/rustc_cfg.rs | 9 ++--- crates/project-model/src/sysroot.rs | 33 ++++++++------- .../project-model/src/target_data_layout.rs | 7 ++-- crates/project-model/src/workspace.rs | 40 +++++++++---------- crates/toolchain/src/lib.rs | 4 -- 7 files changed, 54 insertions(+), 64 deletions(-) diff --git a/crates/project-model/src/build_scripts.rs b/crates/project-model/src/build_scripts.rs index 27a8db40a998..709fc0371747 100644 --- a/crates/project-model/src/build_scripts.rs +++ b/crates/project-model/src/build_scripts.rs @@ -71,8 +71,7 @@ impl WorkspaceBuildScripts { cmd } _ => { - let mut cmd = Command::new(Tool::Cargo.path()); - Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot); + let mut cmd = Sysroot::tool(sysroot, Tool::Cargo); cmd.args(["check", "--quiet", "--workspace", "--message-format=json"]); cmd.args(&config.extra_args); @@ -430,8 +429,7 @@ impl WorkspaceBuildScripts { } let res = (|| { let target_libdir = (|| { - let mut cargo_config = Command::new(Tool::Cargo.path()); - Sysroot::set_rustup_toolchain_env(&mut cargo_config, sysroot); + let mut cargo_config = Sysroot::tool(sysroot, Tool::Cargo); cargo_config.envs(extra_env); cargo_config .current_dir(current_dir) @@ -440,7 +438,7 @@ impl WorkspaceBuildScripts { if let Ok(it) = utf8_stdout(cargo_config) { return Ok(it); } - let mut cmd = Sysroot::rustc(sysroot); + let mut cmd = Sysroot::tool(sysroot, Tool::Rustc); cmd.envs(extra_env); cmd.args(["--print", "target-libdir"]); utf8_stdout(cmd) diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs index 609b1f67b57d..53b41ea1e87b 100644 --- a/crates/project-model/src/cargo_workspace.rs +++ b/crates/project-model/src/cargo_workspace.rs @@ -1,8 +1,8 @@ //! See [`CargoWorkspace`]. +use std::ops; use std::path::PathBuf; use std::str::from_utf8; -use std::{ops, process::Command}; use anyhow::Context; use base_db::Edition; @@ -243,8 +243,11 @@ impl CargoWorkspace { ) -> anyhow::Result { let targets = find_list_of_build_targets(config, cargo_toml, sysroot); + let cargo = Sysroot::tool(sysroot, Tool::Cargo); let mut meta = MetadataCommand::new(); - meta.cargo_path(Tool::Cargo.path()); + meta.cargo_path(cargo.get_program()); + cargo.get_envs().for_each(|(var, val)| _ = meta.env(var, val.unwrap_or_default())); + config.extra_env.iter().for_each(|(var, val)| _ = meta.env(var, val)); meta.manifest_path(cargo_toml.to_path_buf()); match &config.features { CargoFeatures::All => { @@ -291,10 +294,7 @@ impl CargoWorkspace { progress("metadata".to_owned()); (|| -> Result { - let mut command = meta.cargo_command(); - Sysroot::set_rustup_toolchain_env(&mut command, sysroot); - command.envs(&config.extra_env); - let output = command.output()?; + let output = meta.cargo_command().output()?; if !output.status.success() { return Err(cargo_metadata::Error::CargoMetadata { stderr: String::from_utf8(output.stderr)?, @@ -501,7 +501,7 @@ fn rustc_discover_host_triple( extra_env: &FxHashMap, sysroot: Option<&Sysroot>, ) -> Option { - let mut rustc = Sysroot::rustc(sysroot); + let mut rustc = Sysroot::tool(sysroot, Tool::Rustc); rustc.envs(extra_env); rustc.current_dir(cargo_toml.parent()).arg("-vV"); tracing::debug!("Discovering host platform by {:?}", rustc); @@ -529,8 +529,7 @@ fn cargo_config_build_target( extra_env: &FxHashMap, sysroot: Option<&Sysroot>, ) -> Vec { - let mut cargo_config = Command::new(Tool::Cargo.path()); - Sysroot::set_rustup_toolchain_env(&mut cargo_config, sysroot); + let mut cargo_config = Sysroot::tool(sysroot, Tool::Cargo); cargo_config.envs(extra_env); cargo_config .current_dir(cargo_toml.parent()) diff --git a/crates/project-model/src/rustc_cfg.rs b/crates/project-model/src/rustc_cfg.rs index 001296fb0002..501b1fdc8c5b 100644 --- a/crates/project-model/src/rustc_cfg.rs +++ b/crates/project-model/src/rustc_cfg.rs @@ -1,9 +1,8 @@ //! Runs `rustc --print cfg` to get built-in cfg flags. -use std::process::Command; - use anyhow::Context; use rustc_hash::FxHashMap; +use toolchain::Tool; use crate::{cfg_flag::CfgFlag, utf8_stdout, ManifestPath, Sysroot}; @@ -69,8 +68,8 @@ fn get_rust_cfgs( ) -> anyhow::Result { let sysroot = match config { RustcCfgConfig::Cargo(sysroot, cargo_toml) => { - let mut cmd = Command::new(toolchain::Tool::Cargo.path()); - Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot); + let mut cmd = Sysroot::tool(sysroot, Tool::Cargo); + cmd.envs(extra_env); cmd.current_dir(cargo_toml.parent()) .args(["rustc", "-Z", "unstable-options", "--print", "cfg"]) @@ -90,7 +89,7 @@ fn get_rust_cfgs( RustcCfgConfig::Rustc(sysroot) => sysroot, }; - let mut cmd = Sysroot::rustc(sysroot); + let mut cmd = Sysroot::tool(sysroot, Tool::Rustc); cmd.envs(extra_env); cmd.args(["--print", "cfg", "-O"]); if let Some(target) = target { diff --git a/crates/project-model/src/sysroot.rs b/crates/project-model/src/sysroot.rs index a486a38510a8..3127bae8b0c9 100644 --- a/crates/project-model/src/sysroot.rs +++ b/crates/project-model/src/sysroot.rs @@ -193,23 +193,26 @@ impl Sysroot { Ok(Sysroot::load(sysroot_dir, Some(sysroot_src_dir), metadata)) } - pub fn set_rustup_toolchain_env(cmd: &mut Command, sysroot: Option<&Self>) { - if let Some(sysroot) = sysroot { - cmd.env("RUSTUP_TOOLCHAIN", AsRef::::as_ref(&sysroot.root)); - } - } - - /// Returns a `Command` that is configured to run `rustc` from the sysroot if it exists, - /// otherwise returns what [toolchain::Tool::Rustc] returns. - pub fn rustc(sysroot: Option<&Self>) -> Command { - let mut cmd = Command::new(match sysroot { + /// Returns a command to run a tool preferring the cargo proxies if the sysroot exists. + pub fn tool(sysroot: Option<&Self>, tool: Tool) -> Command { + match sysroot { Some(sysroot) => { - toolchain::Tool::Rustc.path_in_or_discover(sysroot.root.join("bin").as_ref()) + // special case rustc, we can look that up directly in the sysroot's bin folder + // as it should never invoke another cargo binary + if let Tool::Rustc = tool { + if let Some(path) = + probe_for_binary(sysroot.root.join("bin").join(Tool::Rustc.name()).into()) + { + return Command::new(path); + } + } + + let mut cmd = Command::new(tool.prefer_proxy()); + cmd.env("RUSTUP_TOOLCHAIN", AsRef::::as_ref(&sysroot.root)); + cmd } - None => toolchain::Tool::Rustc.path(), - }); - Self::set_rustup_toolchain_env(&mut cmd, sysroot); - cmd + _ => Command::new(tool.path()), + } } pub fn discover_proc_macro_srv(&self) -> anyhow::Result { diff --git a/crates/project-model/src/target_data_layout.rs b/crates/project-model/src/target_data_layout.rs index df77541762d9..4e810a0232ea 100644 --- a/crates/project-model/src/target_data_layout.rs +++ b/crates/project-model/src/target_data_layout.rs @@ -1,7 +1,7 @@ //! Runs `rustc --print target-spec-json` to get the target_data_layout. -use std::process::Command; use rustc_hash::FxHashMap; +use toolchain::Tool; use crate::{utf8_stdout, ManifestPath, Sysroot}; @@ -28,8 +28,7 @@ pub fn get( }; let sysroot = match config { RustcDataLayoutConfig::Cargo(sysroot, cargo_toml) => { - let mut cmd = Command::new(toolchain::Tool::Cargo.path()); - Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot); + let mut cmd = Sysroot::tool(sysroot, Tool::Cargo); cmd.envs(extra_env); cmd.current_dir(cargo_toml.parent()) .args([ @@ -57,7 +56,7 @@ pub fn get( RustcDataLayoutConfig::Rustc(sysroot) => sysroot, }; - let mut cmd = Sysroot::rustc(sysroot); + let mut cmd = Sysroot::tool(sysroot, Tool::Rustc); cmd.envs(extra_env) .args(["-Z", "unstable-options", "--print", "target-spec-json"]) .env("RUSTC_BOOTSTRAP", "1"); diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index adf15d45fc62..1a138b17bad4 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -2,7 +2,7 @@ //! metadata` or `rust-project.json`) into representation stored in the salsa //! database -- `CrateGraph`. -use std::{collections::VecDeque, fmt, fs, iter, process::Command, str::FromStr, sync}; +use std::{collections::VecDeque, fmt, fs, iter, str::FromStr, sync}; use anyhow::{format_err, Context}; use base_db::{ @@ -172,11 +172,13 @@ impl fmt::Debug for ProjectWorkspace { fn get_toolchain_version( current_dir: &AbsPath, - mut cmd: Command, + sysroot: Option<&Sysroot>, + tool: Tool, extra_env: &FxHashMap, prefix: &str, ) -> Result, anyhow::Error> { let cargo_version = utf8_stdout({ + let mut cmd = Sysroot::tool(sysroot, tool); cmd.envs(extra_env); cmd.arg("--version").current_dir(current_dir); cmd @@ -297,11 +299,8 @@ impl ProjectWorkspace { let toolchain = get_toolchain_version( cargo_toml.parent(), - { - let mut cmd = Command::new(toolchain::Tool::Cargo.path()); - Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot_ref); - cmd - }, + sysroot_ref, + Tool::Cargo, &config.extra_env, "cargo ", )?; @@ -386,7 +385,8 @@ impl ProjectWorkspace { let data_layout_config = RustcDataLayoutConfig::Rustc(sysroot_ref); let toolchain = match get_toolchain_version( project_json.path(), - Sysroot::rustc(sysroot_ref), + sysroot_ref, + Tool::Rustc, extra_env, "rustc ", ) { @@ -433,18 +433,15 @@ impl ProjectWorkspace { }; let sysroot_ref = sysroot.as_ref().ok(); - let toolchain = match get_toolchain_version( - dir, - Sysroot::rustc(sysroot_ref), - &config.extra_env, - "rustc ", - ) { - Ok(it) => it, - Err(e) => { - tracing::error!("{e}"); - None - } - }; + let toolchain = + match get_toolchain_version(dir, sysroot_ref, Tool::Rustc, &config.extra_env, "rustc ") + { + Ok(it) => it, + Err(e) => { + tracing::error!("{e}"); + None + } + }; let rustc_cfg = rustc_cfg::get(None, &config.extra_env, RustcCfgConfig::Rustc(sysroot_ref)); let data_layout = target_data_layout::get( @@ -1573,8 +1570,7 @@ fn cargo_config_env( extra_env: &FxHashMap, sysroot: Option<&Sysroot>, ) -> FxHashMap { - let mut cargo_config = Command::new(Tool::Cargo.path()); - Sysroot::set_rustup_toolchain_env(&mut cargo_config, sysroot); + let mut cargo_config = Sysroot::tool(sysroot, Tool::Cargo); cargo_config.envs(extra_env); cargo_config .current_dir(cargo_toml.parent()) diff --git a/crates/toolchain/src/lib.rs b/crates/toolchain/src/lib.rs index e65a060672ee..a77fed585af7 100644 --- a/crates/toolchain/src/lib.rs +++ b/crates/toolchain/src/lib.rs @@ -58,10 +58,6 @@ impl Tool { probe_for_binary(path.join(self.name())) } - pub fn path_in_or_discover(self, path: &Path) -> PathBuf { - probe_for_binary(path.join(self.name())).unwrap_or_else(|| self.path()) - } - pub fn name(self) -> &'static str { match self { Tool::Cargo => "cargo", From b20e46737301157a484518e2a56adaf996fe77c8 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 5 Mar 2024 11:06:36 +0100 Subject: [PATCH 32/69] internal: Adjust a few things for trait assoc item hovers --- crates/hir-ty/src/display.rs | 10 +- crates/hir/src/display.rs | 49 ++- crates/ide/src/hover.rs | 2 +- crates/ide/src/hover/render.rs | 2 +- crates/ide/src/hover/tests.rs | 622 ++++++++++++++++------------- crates/ide/src/static_index.rs | 2 +- crates/rust-analyzer/src/config.rs | 2 +- 7 files changed, 381 insertions(+), 308 deletions(-) diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 328dea87ac11..fe191a456a9a 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -63,7 +63,7 @@ pub struct HirFormatter<'a> { buf: String, curr_size: usize, pub(crate) max_size: Option, - pub limited_size: Option, + pub entity_limit: Option, omit_verbose_types: bool, closure_style: ClosureStyle, display_target: DisplayTarget, @@ -148,8 +148,8 @@ pub trait HirDisplay { } } - /// Returns a `Display`able type that is human-readable and tries to limit the item inside this type. - /// Use this for showing types which may contain two many item when user hover on, like `trait`, `struct`, `enum` + /// Returns a `Display`able type that is human-readable and tries to limit the number of items inside. + /// Use this for showing definitions which may contain too many items, like `trait`, `struct`, `enum` fn display_limited<'a>( &'a self, db: &'a dyn HirDatabase, @@ -184,7 +184,7 @@ pub trait HirDisplay { buf: String::with_capacity(20), curr_size: 0, max_size: None, - limited_size: None, + entity_limit: None, omit_verbose_types: false, closure_style: ClosureStyle::ImplFn, display_target: DisplayTarget::SourceCode { module_id, allow_opaque }, @@ -352,7 +352,7 @@ impl HirDisplayWrapper<'_, T> { buf: String::with_capacity(20), curr_size: 0, max_size: self.max_size, - limited_size: self.limited_size, + entity_limit: self.limited_size, omit_verbose_types: self.omit_verbose_types, display_target: self.display_target, closure_style: self.closure_style, diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 20ba72d998c3..cdc0db8653c1 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -596,33 +596,32 @@ impl HirDisplay for Trait { write_generic_params(def_id, f)?; write_where_clause(def_id, f)?; - let assoc_items = self.items(f.db); - let assoc_items_size = assoc_items.len(); - let limited_size = f.limited_size.unwrap_or(assoc_items_size); - if assoc_items.is_empty() { - f.write_str(" {}")?; - } else { - f.write_str(" {\n")?; - for (index, item) in assoc_items.iter().enumerate() { - f.write_str(" ")?; - match item { - AssocItem::Function(func) => { - func.hir_fmt(f)?; - } - AssocItem::Const(cst) => { - cst.hir_fmt(f)?; - } - AssocItem::TypeAlias(type_alias) => { - type_alias.hir_fmt(f)?; - } - }; - f.write_str(",\n")?; - if index + 1 == limited_size && index + 1 != assoc_items_size { - f.write_str(" ...\n")?; - break; + if let Some(limit) = f.entity_limit { + let assoc_items = self.items(f.db); + let count = assoc_items.len().min(limit); + if count == 0 { + if assoc_items.is_empty() { + f.write_str(" {}")?; + } else { + f.write_str(" { /* … */ }")?; } + } else { + f.write_str(" {\n")?; + for item in &assoc_items[..count] { + f.write_str(" ")?; + match item { + AssocItem::Function(func) => func.hir_fmt(f), + AssocItem::Const(cst) => cst.hir_fmt(f), + AssocItem::TypeAlias(type_alias) => type_alias.hir_fmt(f), + }?; + f.write_str(";\n")?; + } + + if assoc_items.len() > count { + f.write_str(" /* … */\n")?; + } + f.write_str("}")?; } - f.write_str("}")?; } Ok(()) diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index b6877c5e8ce9..8f4c629b5813 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -32,7 +32,7 @@ pub struct HoverConfig { pub documentation: bool, pub keywords: bool, pub format: HoverDocFormat, - pub trait_assoc_items_size: Option, + pub max_trait_assoc_items_count: Option, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index f528bd512cce..d1d039534d51 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -408,7 +408,7 @@ pub(super) fn definition( let mod_path = definition_mod_path(db, &def); let label = match def { Definition::Trait(trait_) => { - trait_.display_limited(db, config.trait_assoc_items_size).to_string() + trait_.display_limited(db, config.max_trait_assoc_items_count).to_string() } _ => def.label(db), }; diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index cec1375271e6..c3cd6513dc61 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -17,7 +17,7 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig { documentation: true, format: HoverDocFormat::Markdown, keywords: true, - trait_assoc_items_size: None, + max_trait_assoc_items_count: None, }; fn check_hover_no_result(ra_fixture: &str) { @@ -49,6 +49,28 @@ fn check(ra_fixture: &str, expect: Expect) { expect.assert_eq(&actual) } +#[track_caller] +fn check_assoc_count(count: usize, ra_fixture: &str, expect: Expect) { + let (analysis, position) = fixture::position(ra_fixture); + let hover = analysis + .hover( + &HoverConfig { + links_in_hover: true, + max_trait_assoc_items_count: Some(count), + ..HOVER_BASE_CONFIG + }, + FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) }, + ) + .unwrap() + .unwrap(); + + let content = analysis.db.file_text(position.file_id); + let hovered_element = &content[hover.range]; + + let actual = format!("*{hovered_element}*\n{}\n", hover.info.markup); + expect.assert_eq(&actual) +} + fn check_hover_no_links(ra_fixture: &str, expect: Expect) { let (analysis, position) = fixture::position(ra_fixture); let hover = analysis @@ -412,7 +434,7 @@ fn main() { name: "FnOnce", kind: Trait, container_name: "function", - description: "pub trait FnOnce\nwhere\n Args: Tuple, {\n pub type Output,\n pub extern \"rust-call\" fn call_once(self, args: Args) -> Self::Output,\n}", + description: "pub trait FnOnce\nwhere\n Args: Tuple,", }, }, ], @@ -2673,26 +2695,26 @@ fn foo() -> impl Foo {} fn main() { let s$0t = foo(); } "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..12, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..12, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -2707,39 +2729,39 @@ fn foo() -> impl Foo {} fn main() { let s$0t = foo(); } "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..15, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..15, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - HoverGotoTypeData { - mod_path: "test::S", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 16..25, - focus_range: 23..24, - name: "S", - kind: Struct, - description: "struct S", - }, + }, + HoverGotoTypeData { + mod_path: "test::S", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 16..25, + focus_range: 23..24, + name: "S", + kind: Struct, + description: "struct S", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -2767,7 +2789,7 @@ fn main() { let s$0t = foo(); } focus_range: 19..22, name: "Bar", kind: Trait, - description: "trait Bar {}", + description: "trait Bar", }, }, HoverGotoTypeData { @@ -2780,7 +2802,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo {}", + description: "trait Foo", }, }, ], @@ -2817,7 +2839,7 @@ fn main() { let s$0t = foo(); } focus_range: 22..25, name: "Bar", kind: Trait, - description: "trait Bar {}", + description: "trait Bar", }, }, HoverGotoTypeData { @@ -2830,7 +2852,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo {}", + description: "trait Foo", }, }, HoverGotoTypeData { @@ -2874,26 +2896,26 @@ trait Foo {} fn foo(ar$0g: &impl Foo) {} "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..12, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..12, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -2921,7 +2943,7 @@ fn foo(ar$0g: &impl Foo + Bar) {} focus_range: 19..22, name: "Bar", kind: Trait, - description: "trait Bar {}", + description: "trait Bar", }, }, HoverGotoTypeData { @@ -2934,7 +2956,7 @@ fn foo(ar$0g: &impl Foo + Bar) {} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo {}", + description: "trait Foo", }, }, HoverGotoTypeData { @@ -2989,7 +3011,7 @@ pub mod future { name: "Future", kind: Trait, container_name: "future", - description: "pub trait Future {}", + description: "pub trait Future", }, }, HoverGotoTypeData { @@ -3021,39 +3043,39 @@ struct S {} fn foo(ar$0g: &impl Foo) {} "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..15, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..15, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - HoverGotoTypeData { - mod_path: "test::S", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 16..27, - focus_range: 23..24, - name: "S", - kind: Struct, - description: "struct S {}", - }, + }, + HoverGotoTypeData { + mod_path: "test::S", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 16..27, + focus_range: 23..24, + name: "S", + kind: Struct, + description: "struct S {}", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -3071,39 +3093,39 @@ fn foo() -> B {} fn main() { let s$0t = foo(); } "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::B", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 42..55, - focus_range: 49..50, - name: "B", - kind: Struct, - description: "struct B {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::B", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 42..55, + focus_range: 49..50, + name: "B", + kind: Struct, + description: "struct B {}", }, - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..12, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + }, + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..12, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -3115,26 +3137,26 @@ trait Foo {} fn foo(ar$0g: &dyn Foo) {} "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..12, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..12, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -3147,39 +3169,39 @@ struct S {} fn foo(ar$0g: &dyn Foo) {} "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..15, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..15, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - HoverGotoTypeData { - mod_path: "test::S", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 16..27, - focus_range: 23..24, - name: "S", - kind: Struct, - description: "struct S {}", - }, + }, + HoverGotoTypeData { + mod_path: "test::S", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 16..27, + focus_range: 23..24, + name: "S", + kind: Struct, + description: "struct S {}", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -3221,7 +3243,7 @@ fn foo(a$0rg: &impl ImplTrait>>>) {} focus_range: 28..36, name: "DynTrait", kind: Trait, - description: "trait DynTrait {}", + description: "trait DynTrait", }, }, HoverGotoTypeData { @@ -3234,7 +3256,7 @@ fn foo(a$0rg: &impl ImplTrait>>>) {} focus_range: 6..15, name: "ImplTrait", kind: Trait, - description: "trait ImplTrait {}", + description: "trait ImplTrait", }, }, HoverGotoTypeData { @@ -3276,26 +3298,26 @@ fn test() -> impl Foo { S {} } fn main() { let s$0t = test().get(); } "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..62, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {\n type Item,\n fn get(self) -> Self::Item,\n}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..62, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -3341,26 +3363,26 @@ trait Foo {} fn foo(t: T$0){} "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..12, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..12, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -6330,71 +6352,96 @@ impl T for () { #[test] fn hover_trait_show_assoc_items() { - check( + check_assoc_count( + 0, r#" trait T {} impl T$0 for () {} "#, expect![[r#" - *T* + *T* - ```rust - test - ``` + ```rust + test + ``` - ```rust - trait T {} - ``` + ```rust + trait T {} + ``` "#]], ); - check( + check_assoc_count( + 1, + r#" +trait T {} +impl T$0 for () {} +"#, + expect![[r#" + *T* + + ```rust + test + ``` + + ```rust + trait T {} + ``` + "#]], + ); + + check_assoc_count( + 0, r#" trait T { fn func() {} + const FLAG: i32 = 34; + type Bar; } impl T$0 for () {} "#, expect![[r#" - *T* + *T* - ```rust - test - ``` + ```rust + test + ``` - ```rust - trait T { - fn func(), - } - ``` + ```rust + trait T { /* … */ } + ``` "#]], ); - check( + check_assoc_count( + 2, r#" trait T { fn func() {} const FLAG: i32 = 34; + type Bar; } impl T$0 for () {} "#, expect![[r#" - *T* + *T* - ```rust - test - ``` + ```rust + test + ``` - ```rust - trait T { - fn func(), - const FLAG: i32, - } - ``` + ```rust + trait T { + fn func(); + const FLAG: i32; + /* … */ + } + ``` "#]], ); - check( + check_assoc_count( + 3, r#" trait T { fn func() {} @@ -6404,19 +6451,46 @@ trait T { impl T$0 for () {} "#, expect![[r#" - *T* + *T* - ```rust - test - ``` + ```rust + test + ``` - ```rust - trait T { - fn func(), - const FLAG: i32, - type Bar, - } - ``` + ```rust + trait T { + fn func(); + const FLAG: i32; + type Bar; + } + ``` + "#]], + ); + + check_assoc_count( + 4, + r#" +trait T { + fn func() {} + const FLAG: i32 = 34; + type Bar; +} +impl T$0 for () {} +"#, + expect![[r#" + *T* + + ```rust + test + ``` + + ```rust + trait T { + fn func(); + const FLAG: i32; + type Bar; + } + ``` "#]], ); } @@ -7532,7 +7606,7 @@ impl Iterator for S { name: "Future", kind: Trait, container_name: "future", - description: "pub trait Future {\n pub type Output,\n pub fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll,\n}", + description: "pub trait Future", }, }, HoverGotoTypeData { @@ -7546,7 +7620,7 @@ impl Iterator for S { name: "Iterator", kind: Trait, container_name: "iterator", - description: "pub trait Iterator {\n pub type Item,\n pub fn next(&mut self) -> Option,\n pub fn nth(&mut self, n: usize) -> Option,\n pub fn by_ref(&mut self) -> &mut Self\nwhere\n Self: Sized,,\n}", + description: "pub trait Iterator", }, }, HoverGotoTypeData { @@ -7559,7 +7633,7 @@ impl Iterator for S { focus_range: 49..56, name: "Notable", kind: Trait, - description: "trait Notable {}", + description: "trait Notable", }, }, HoverGotoTypeData { diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index 0f19da0ac5fb..fe063081f799 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -166,7 +166,7 @@ impl StaticIndex<'_> { documentation: true, keywords: true, format: crate::HoverDocFormat::Markdown, - trait_assoc_items_size: None, + max_trait_assoc_items_count: None, }; let tokens = tokens.filter(|token| { matches!( diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 21a106bc7709..ad3721a99548 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -1682,7 +1682,7 @@ impl Config { } }, keywords: self.data.hover_documentation_keywords_enable, - trait_assoc_items_size: self.data.hover_show_traitAssocItems, + max_trait_assoc_items_count: self.data.hover_show_traitAssocItems, } } From 8844640c6f28bc4459ed8c0b466a20ecf39baa07 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 5 Mar 2024 11:41:46 +0100 Subject: [PATCH 33/69] fix: Put style lints behind disabled-by-default config --- crates/hir-ty/src/diagnostics/expr.rs | 19 ++++++- crates/hir/src/lib.rs | 49 ++++++++++++------- crates/ide-diagnostics/src/lib.rs | 4 +- .../rust-analyzer/src/cli/analysis_stats.rs | 1 + crates/rust-analyzer/src/config.rs | 3 ++ docs/user/generated_config.adoc | 5 ++ editors/code/package.json | 5 ++ 7 files changed, 66 insertions(+), 20 deletions(-) diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs index 1a134e6d780e..dfc0a25bf465 100644 --- a/crates/hir-ty/src/diagnostics/expr.rs +++ b/crates/hir-ty/src/diagnostics/expr.rs @@ -60,12 +60,17 @@ pub enum BodyValidationDiagnostic { } impl BodyValidationDiagnostic { - pub fn collect(db: &dyn HirDatabase, owner: DefWithBodyId) -> Vec { + pub fn collect( + db: &dyn HirDatabase, + owner: DefWithBodyId, + validate_lints: bool, + ) -> Vec { let _p = tracing::span!(tracing::Level::INFO, "BodyValidationDiagnostic::collect").entered(); let infer = db.infer(owner); let body = db.body(owner); - let mut validator = ExprValidator { owner, body, infer, diagnostics: Vec::new() }; + let mut validator = + ExprValidator { owner, body, infer, diagnostics: Vec::new(), validate_lints }; validator.validate_body(db); validator.diagnostics } @@ -76,6 +81,7 @@ struct ExprValidator { body: Arc, infer: Arc, diagnostics: Vec, + validate_lints: bool, } impl ExprValidator { @@ -139,6 +145,9 @@ impl ExprValidator { expr: &Expr, filter_map_next_checker: &mut Option, ) { + if !self.validate_lints { + return; + } // Check that the number of arguments matches the number of parameters. if self.infer.expr_type_mismatches().next().is_some() { @@ -308,6 +317,9 @@ impl ExprValidator { } fn check_for_trailing_return(&mut self, body_expr: ExprId, body: &Body) { + if !self.validate_lints { + return; + } match &body.exprs[body_expr] { Expr::Block { statements, tail, .. } => { let last_stmt = tail.or_else(|| match statements.last()? { @@ -340,6 +352,9 @@ impl ExprValidator { } fn check_for_unnecessary_else(&mut self, id: ExprId, expr: &Expr, db: &dyn HirDatabase) { + if !self.validate_lints { + return; + } if let Expr::If { condition: _, then_branch, else_branch } = expr { if else_branch.is_none() { return; diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 1e16f78ca2d3..4872c47c31d0 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -365,7 +365,7 @@ impl ModuleDef { Some(name) } - pub fn diagnostics(self, db: &dyn HirDatabase) -> Vec { + pub fn diagnostics(self, db: &dyn HirDatabase, style_lints: bool) -> Vec { let id = match self { ModuleDef::Adt(it) => match it { Adt::Struct(it) => it.id.into(), @@ -387,7 +387,7 @@ impl ModuleDef { match self.as_def_with_body() { Some(def) => { - def.diagnostics(db, &mut acc); + def.diagnostics(db, &mut acc, style_lints); } None => { for diag in hir_ty::diagnostics::incorrect_case(db, id) { @@ -541,7 +541,12 @@ impl Module { } /// Fills `acc` with the module's diagnostics. - pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec) { + pub fn diagnostics( + self, + db: &dyn HirDatabase, + acc: &mut Vec, + style_lints: bool, + ) { let name = self.name(db); let _p = tracing::span!(tracing::Level::INFO, "Module::diagnostics", ?name); let def_map = self.id.def_map(db.upcast()); @@ -558,9 +563,9 @@ impl Module { ModuleDef::Module(m) => { // Only add diagnostics from inline modules if def_map[m.id.local_id].origin.is_inline() { - m.diagnostics(db, acc) + m.diagnostics(db, acc, style_lints) } - acc.extend(def.diagnostics(db)) + acc.extend(def.diagnostics(db, style_lints)) } ModuleDef::Trait(t) => { for diag in db.trait_data_with_diagnostics(t.id).1.iter() { @@ -568,10 +573,10 @@ impl Module { } for item in t.items(db) { - item.diagnostics(db, acc); + item.diagnostics(db, acc, style_lints); } - acc.extend(def.diagnostics(db)) + acc.extend(def.diagnostics(db, style_lints)) } ModuleDef::Adt(adt) => { match adt { @@ -587,17 +592,17 @@ impl Module { } Adt::Enum(e) => { for v in e.variants(db) { - acc.extend(ModuleDef::Variant(v).diagnostics(db)); + acc.extend(ModuleDef::Variant(v).diagnostics(db, style_lints)); for diag in db.enum_variant_data_with_diagnostics(v.id).1.iter() { emit_def_diagnostic(db, acc, diag); } } } } - acc.extend(def.diagnostics(db)) + acc.extend(def.diagnostics(db, style_lints)) } ModuleDef::Macro(m) => emit_macro_def_diagnostics(db, acc, m), - _ => acc.extend(def.diagnostics(db)), + _ => acc.extend(def.diagnostics(db, style_lints)), } } self.legacy_macros(db).into_iter().for_each(|m| emit_macro_def_diagnostics(db, acc, m)); @@ -738,7 +743,7 @@ impl Module { } for &item in &db.impl_data(impl_def.id).items { - AssocItem::from(item).diagnostics(db, acc); + AssocItem::from(item).diagnostics(db, acc, style_lints); } } } @@ -1616,14 +1621,19 @@ impl DefWithBody { } } - pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec) { + pub fn diagnostics( + self, + db: &dyn HirDatabase, + acc: &mut Vec, + style_lints: bool, + ) { db.unwind_if_cancelled(); let krate = self.module(db).id.krate(); let (body, source_map) = db.body_with_source_map(self.into()); for (_, def_map) in body.blocks(db.upcast()) { - Module { id: def_map.module_id(DefMap::ROOT) }.diagnostics(db, acc); + Module { id: def_map.module_id(DefMap::ROOT) }.diagnostics(db, acc, style_lints); } for diag in source_map.diagnostics() { @@ -1784,7 +1794,7 @@ impl DefWithBody { } } - for diagnostic in BodyValidationDiagnostic::collect(db, self.into()) { + for diagnostic in BodyValidationDiagnostic::collect(db, self.into(), style_lints) { acc.extend(AnyDiagnostic::body_validation_diagnostic(db, diagnostic, &source_map)); } @@ -2897,13 +2907,18 @@ impl AssocItem { } } - pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec) { + pub fn diagnostics( + self, + db: &dyn HirDatabase, + acc: &mut Vec, + style_lints: bool, + ) { match self { AssocItem::Function(func) => { - DefWithBody::from(func).diagnostics(db, acc); + DefWithBody::from(func).diagnostics(db, acc, style_lints); } AssocItem::Const(const_) => { - DefWithBody::from(const_).diagnostics(db, acc); + DefWithBody::from(const_).diagnostics(db, acc, style_lints); } AssocItem::TypeAlias(type_alias) => { for diag in hir_ty::diagnostics::incorrect_case(db, type_alias.id.into()) { diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs index 9a7e1a2ae6d6..0df6f0e0373c 100644 --- a/crates/ide-diagnostics/src/lib.rs +++ b/crates/ide-diagnostics/src/lib.rs @@ -227,6 +227,7 @@ pub struct DiagnosticsConfig { pub disable_experimental: bool, pub disabled: FxHashSet, pub expr_fill_default: ExprFillDefaultMode, + pub style_lints: bool, // FIXME: We may want to include a whole `AssistConfig` here pub insert_use: InsertUseConfig, pub prefer_no_std: bool, @@ -245,6 +246,7 @@ impl DiagnosticsConfig { disable_experimental: Default::default(), disabled: Default::default(), expr_fill_default: Default::default(), + style_lints: true, insert_use: InsertUseConfig { granularity: ImportGranularity::Preserve, enforce_granularity: false, @@ -324,7 +326,7 @@ pub fn diagnostics( let mut diags = Vec::new(); if let Some(m) = module { - m.diagnostics(db, &mut diags); + m.diagnostics(db, &mut diags, config.style_lints); } for diag in diags { diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index 7e027c9f9284..ef184032bfb0 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -982,6 +982,7 @@ impl flags::AnalysisStats { }, prefer_no_std: false, prefer_prelude: true, + style_lints: false, }, ide::AssistResolveStrategy::All, file_id, diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 21a106bc7709..906b000829e2 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -311,6 +311,8 @@ config_data! { /// Map of prefixes to be substituted when parsing diagnostic file paths. /// This should be the reverse mapping of what is passed to `rustc` as `--remap-path-prefix`. diagnostics_remapPrefix: FxHashMap = "{}", + /// Whether to run additional style lints. + diagnostics_styleLints_enable: bool = "false", /// List of warnings that should be displayed with hint severity. /// /// The warnings will be indicated by faded text or three dots in code @@ -1162,6 +1164,7 @@ impl Config { insert_use: self.insert_use_config(), prefer_no_std: self.data.imports_preferNoStd, prefer_prelude: self.data.imports_preferPrelude, + style_lints: self.data.diagnostics_styleLints_enable, } } diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 0fb275961bef..5e782b783111 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -386,6 +386,11 @@ have more false positives than usual. Map of prefixes to be substituted when parsing diagnostic file paths. This should be the reverse mapping of what is passed to `rustc` as `--remap-path-prefix`. -- +[[rust-analyzer.diagnostics.styleLints.enable]]rust-analyzer.diagnostics.styleLints.enable (default: `false`):: ++ +-- +Whether to run additional style lints. +-- [[rust-analyzer.diagnostics.warningsAsHint]]rust-analyzer.diagnostics.warningsAsHint (default: `[]`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index 3a276409fb6b..16d3dcbab6fe 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -948,6 +948,11 @@ "default": {}, "type": "object" }, + "rust-analyzer.diagnostics.styleLints.enable": { + "markdownDescription": "Whether to run additional style lints.", + "default": false, + "type": "boolean" + }, "rust-analyzer.diagnostics.warningsAsHint": { "markdownDescription": "List of warnings that should be displayed with hint severity.\n\nThe warnings will be indicated by faded text or three dots in code\nand will not show up in the `Problems Panel`.", "default": [], From 00a6cc06642d6dc0cf27bd0d3cf7dae20cd28030 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 5 Mar 2024 12:00:21 +0100 Subject: [PATCH 34/69] Update Cargo.lock --- Cargo.lock | 616 +++++++++--------- Cargo.toml | 20 +- crates/ide-db/src/prime_caches.rs | 2 +- crates/ide/Cargo.toml | 10 +- crates/proc-macro-api/Cargo.toml | 8 +- crates/proc-macro-srv/Cargo.toml | 8 +- crates/salsa/Cargo.toml | 1 - crates/salsa/src/runtime.rs | 2 +- crates/salsa/tests/cycles.rs | 1 - .../parallel/parallel_cycle_all_recover.rs | 1 - .../parallel/parallel_cycle_mid_recover.rs | 1 - .../parallel/parallel_cycle_none_recover.rs | 1 - .../parallel/parallel_cycle_one_recovers.rs | 1 - 13 files changed, 332 insertions(+), 340 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3667dec23a6f..9c26f6648dd1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.19.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -28,9 +28,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" [[package]] name = "arbitrary" @@ -52,16 +52,16 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.67" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", "cfg-if", "libc", - "miniz_oxide 0.6.2", - "object 0.30.4", + "miniz_oxide", + "object 0.32.2", "rustc-demangle", ] @@ -90,30 +90,30 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "camino" -version = "1.1.4" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" dependencies = [ "serde", ] [[package]] name = "cargo-platform" -version = "0.1.2" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f" dependencies = [ "serde", ] @@ -134,9 +134,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "a0ba8f7aaa012f30d5b2861462f6708eccd49c3c39863fe083a308035f63d723" [[package]] name = "cfg" @@ -176,7 +176,7 @@ version = "0.96.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff550c2cdd63ff74394214dce03d06386928a641c0f08837535f04af573a966d" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "chalk-derive", "lazy_static", ] @@ -216,7 +216,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5080df6b0f0ecb76cab30808f00d937ba725cebe266a3da8cd89dff92f2a9916" dependencies = [ - "nix 0.26.2", + "nix 0.26.4", "winapi", ] @@ -239,64 +239,55 @@ checksum = "0d48d8f76bd9331f19fe2aaf3821a9f9fb32c3963e1e3d6ce82a8c09cef7444a" [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "ctrlc" -version = "3.4.1" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf" +checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b" dependencies = [ "nix 0.27.1", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -312,6 +303,15 @@ dependencies = [ "parking_lot_core", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "derive_arbitrary" version = "1.3.2" @@ -343,9 +343,9 @@ checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1" [[package]] name = "either" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "ena" @@ -356,20 +356,11 @@ dependencies = [ "log", ] -[[package]] -name = "env_logger" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" -dependencies = [ - "log", -] - [[package]] name = "equivalent" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "expect-test" @@ -383,14 +374,14 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.22" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", - "windows-sys", + "redox_syscall", + "windows-sys 0.52.0", ] [[package]] @@ -401,12 +392,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.26" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", - "miniz_oxide 0.7.1", + "miniz_oxide", ] [[package]] @@ -427,9 +418,9 @@ dependencies = [ [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -462,9 +453,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.3" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "hashbrown" @@ -480,12 +471,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hir" @@ -516,7 +504,7 @@ version = "0.0.0" dependencies = [ "arrayvec", "base-db", - "bitflags 2.4.1", + "bitflags 2.4.2", "cfg", "cov-mark", "dashmap", @@ -579,7 +567,7 @@ version = "0.0.0" dependencies = [ "arrayvec", "base-db", - "bitflags 2.4.1", + "bitflags 2.4.2", "chalk-derive", "chalk-ir", "chalk-recursive", @@ -600,7 +588,7 @@ dependencies = [ "oorandom", "project-model", "ra-ap-rustc_abi", - "ra-ap-rustc_index 0.35.0", + "ra-ap-rustc_index", "ra-ap-rustc_pattern_analysis", "rustc-hash", "scoped-tls", @@ -618,11 +606,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -773,9 +761,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -783,9 +771,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" dependencies = [ "equivalent", "hashbrown", @@ -823,18 +811,18 @@ dependencies = [ [[package]] name = "itertools" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "jod-thread" @@ -844,9 +832,9 @@ checksum = "8b23360e99b8717f20aaa4598f5a6541efbe30630039fbc7706cf954a87947ae" [[package]] name = "kqueue" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" dependencies = [ "kqueue-sys", "libc", @@ -854,9 +842,9 @@ dependencies = [ [[package]] name = "kqueue-sys" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" dependencies = [ "bitflags 1.3.2", "libc", @@ -880,25 +868,25 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb" +checksum = "2caa5afb8bf9f3a2652760ce7d4f62d21c4d5a423e68466fca30df82f2330164" dependencies = [ "cfg-if", - "windows-sys", + "windows-targets 0.52.4", ] [[package]] name = "libmimalloc-sys" -version = "0.1.33" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4ac0e912c8ef1b735e92369695618dc5b1819f5a7bf3f167301a3ba1cea515e" +checksum = "3979b5c37ece694f1f5e51e7ecc871fdb0f517ed04ee45f88d15d6d553cb9664" dependencies = [ "cc", "libc", @@ -953,9 +941,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -963,9 +951,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "lsp-server" @@ -1046,27 +1034,18 @@ dependencies = [ [[package]] name = "mimalloc" -version = "0.1.37" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e2894987a3459f3ffb755608bd82188f8ed00d0ae077f1edea29c068d639d98" +checksum = "fa01922b5ea280a911e323e4d2fd24b7fe5cc4042e0d2cda3c40775cdc4bdc9c" dependencies = [ "libmimalloc-sys", ] [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" -dependencies = [ - "adler", -] - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] @@ -1080,7 +1059,7 @@ dependencies = [ "libc", "log", "wasi", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1089,19 +1068,18 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "359f76430b20a79f9e20e115b3428614e654f04fab314482fc0fda0ebd3c6044" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "nix" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", "cfg-if", "libc", - "static_assertions", ] [[package]] @@ -1110,7 +1088,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "cfg-if", "libc", ] @@ -1127,7 +1105,7 @@ version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "crossbeam-channel", "filetime", "fsevent-sys", @@ -1137,7 +1115,7 @@ dependencies = [ "log", "mio", "walkdir", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1146,14 +1124,20 @@ version = "0.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c073d3c1930d0751774acf49e66653acecb416c3a54c6ec095a9b11caddb5a68" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ "hermit-abi", "libc", @@ -1161,27 +1145,27 @@ dependencies = [ [[package]] name = "object" -version = "0.30.4" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "object" -version = "0.32.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" +checksum = "d8dd6c0cdf9429bce006e1362bfce61fa1bfd8c898a643ed8d2b471934701d3d" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "oorandom" @@ -1207,9 +1191,9 @@ checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", + "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] @@ -1227,9 +1211,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "paths" @@ -1237,9 +1221,9 @@ version = "0.0.0" [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "perf-event" @@ -1272,9 +1256,15 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "powerfmt" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" @@ -1290,7 +1280,7 @@ dependencies = [ "indexmap", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "memmap2", - "object 0.32.0", + "object 0.33.0", "paths", "rustc-hash", "serde", @@ -1313,7 +1303,7 @@ dependencies = [ "libloading", "mbe", "memmap2", - "object 0.32.0", + "object 0.33.0", "paths", "proc-macro-api", "proc-macro-test", @@ -1341,9 +1331,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -1407,11 +1397,11 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.9.3" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" +checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.2", "memchr", "unicase", ] @@ -1427,35 +1417,24 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.28" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] [[package]] name = "ra-ap-rustc_abi" -version = "0.35.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0baa423a2c2bfd6e4bd40e7215f7ddebd12a649ce0b65078a38b91068895aa" +checksum = "2548746ce549476a7aa982099dfe5139f939099d83077b3393baf5e920292f64" dependencies = [ - "bitflags 2.4.1", - "ra-ap-rustc_index 0.35.0", + "bitflags 2.4.2", + "ra-ap-rustc_index", "tracing", ] -[[package]] -name = "ra-ap-rustc_index" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322b751895cc4a0a2ee0c6ab36ec80bc8abf5f8d76254c482f96f03c27c92ebe" -dependencies = [ - "arrayvec", - "ra-ap-rustc_index_macros 0.35.0", - "smallvec", -] - [[package]] name = "ra-ap-rustc_index" version = "0.40.0" @@ -1463,22 +1442,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "371db64f1be25aae96650b5528c76066ac325f0fe23efec0aab1179d75eea5c3" dependencies = [ "arrayvec", - "ra-ap-rustc_index_macros 0.40.0", + "ra-ap-rustc_index_macros", "smallvec", ] -[[package]] -name = "ra-ap-rustc_index_macros" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "054e25eac52f0506c1309ca4317c11ad4925d7b99eb897f71aa7c3cbafb46c2b" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - [[package]] name = "ra-ap-rustc_index_macros" version = "0.40.0" @@ -1493,9 +1460,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_lexer" -version = "0.35.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8da0fa51a1a97ba4296a1c78fa454815a153b472e2546b6338a0902ad59e015" +checksum = "4f346eb8d73041fd48280373f929803c4650771da631b1d076d5ed0ca4216b48" dependencies = [ "unicode-properties", "unicode-xid", @@ -1503,11 +1470,11 @@ dependencies = [ [[package]] name = "ra-ap-rustc_parse_format" -version = "0.35.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3851f930a54adcb76889983dcd5c00a0c4e206e190e1384dbc00d49b82dfb45e" +checksum = "85f8a94cf47d86b93e7c2440de4308de74e1d5cb71ed3a9df7dcde2550742e6e" dependencies = [ - "ra-ap-rustc_index 0.35.0", + "ra-ap-rustc_index", "ra-ap-rustc_lexer", ] @@ -1517,7 +1484,7 @@ version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9cb49490fadb58e6b8cc825f73157a33730495bfd5c6e9eef067a4b50ad1836" dependencies = [ - "ra-ap-rustc_index 0.40.0", + "ra-ap-rustc_index", "rustc-hash", "rustc_apfloat", "smallvec", @@ -1556,9 +1523,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" dependencies = [ "either", "rayon-core", @@ -1566,23 +1533,14 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", ] -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -1685,9 +1643,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "salsa" @@ -1705,7 +1663,6 @@ dependencies = [ "rustc-hash", "salsa-macros", "smallvec", - "test-log", "tracing", "triomphe", ] @@ -1746,33 +1703,33 @@ checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.17" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", @@ -1781,9 +1738,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "indexmap", "itoa", @@ -1793,9 +1750,9 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.12" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" +checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" dependencies = [ "proc-macro2", "quote", @@ -1804,18 +1761,18 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] [[package]] name = "smallvec" -version = "1.12.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2593d31f82ead8df961d8bd23a64c2ccf2eb5dd34b0a34bfb4dd54011c72009e" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "smol_str" @@ -1828,9 +1785,9 @@ dependencies = [ [[package]] name = "snap" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831" +checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" [[package]] name = "sourcegen" @@ -1858,12 +1815,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "stdx" version = "0.0.0" @@ -1880,9 +1831,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", @@ -1891,14 +1842,13 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", "syn", - "unicode-xid", ] [[package]] @@ -1942,27 +1892,6 @@ dependencies = [ "tt", ] -[[package]] -name = "test-log" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6159ab4116165c99fc88cce31f99fa2c9dbe08d3691cb38da02fc3b45f357d2b" -dependencies = [ - "env_logger", - "test-log-macros", -] - -[[package]] -name = "test-log-macros" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba277e77219e9eea169e8508942db1bf5d8a41ff2db9b20aab5a5aadc9fa25d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "test-utils" version = "0.0.0" @@ -1991,18 +1920,18 @@ checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233" [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", @@ -2011,9 +1940,9 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -2021,9 +1950,9 @@ dependencies = [ [[package]] name = "tikv-jemalloc-ctl" -version = "0.5.0" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e37706572f4b151dff7a0146e040804e9c26fe3a3118591112f05cf12a4216c1" +checksum = "619bfed27d807b54f7f776b9430d4f8060e66ee138a28632ca898584d462c31c" dependencies = [ "libc", "paste", @@ -2032,9 +1961,9 @@ dependencies = [ [[package]] name = "tikv-jemalloc-sys" -version = "0.5.3+5.3.0-patched" +version = "0.5.4+5.3.0-patched" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a678df20055b43e57ef8cddde41cdfda9a3c1a060b67f4c5836dfb1d78543ba8" +checksum = "9402443cb8fd499b6f327e40565234ff34dbda27460c5b47db0db77443dd85d1" dependencies = [ "cc", "libc", @@ -2042,9 +1971,9 @@ dependencies = [ [[package]] name = "tikv-jemallocator" -version = "0.5.0" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20612db8a13a6c06d57ec83953694185a367e16945f66565e8028d2c0bd76979" +checksum = "965fe0c26be5c56c94e38ba547249074803efd52adfb66de62107d95aab3eaca" dependencies = [ "libc", "tikv-jemalloc-sys", @@ -2052,19 +1981,22 @@ dependencies = [ [[package]] name = "time" -version = "0.3.22" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ + "deranged", + "num-conv", + "powerfmt", "serde", "time-core", ] [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "tinyvec" @@ -2189,39 +2121,39 @@ checksum = "a3e5df347f0bf3ec1d670aad6ca5c6a1859cd9ea61d2113125794654ccced68f" [[package]] name = "unicase" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" dependencies = [ "version_check", ] [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] [[package]] name = "unicode-properties" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f91c8b21fbbaa18853c3d0801c78f4fc94cdb976699bb03e832e75f7fd22f0" +checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" [[package]] name = "unicode-xid" @@ -2231,9 +2163,9 @@ checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "url" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -2280,9 +2212,9 @@ dependencies = [ [[package]] name = "walkdir" -version = "2.3.3" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -2312,9 +2244,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -2331,86 +2263,152 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.4", ] [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "write-json" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06069a848f95fceae3e5e03c0ddc8cb78452b56654ee0c8e68f938cf790fb9e3" +checksum = "23f6174b2566cc4a74f95e1367ec343e7fa80c93cc8087f5c4a3d6a1088b2118" [[package]] name = "xflags" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4554b580522d0ca238369c16b8f6ce34524d61dafe7244993754bbd05f2c2ea" +checksum = "7d9e15fbb3de55454b0106e314b28e671279009b363e6f1d8e39fdc3bf048944" dependencies = [ "xflags-macros", ] [[package]] name = "xflags-macros" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58e7b3ca8977093aae6b87b6a7730216fc4c53a6530bab5c43a783cd810c1a8" +checksum = "672423d4fea7ffa2f6c25ba60031ea13dc6258070556f125cc4d790007d4a155" [[package]] name = "xshell" diff --git a/Cargo.toml b/Cargo.toml index e68613c6d384..e8e82914c7c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -84,10 +84,10 @@ 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.35.0", default-features = false } -ra-ap-rustc_parse_format = { version = "0.35.0", default-features = false } -ra-ap-rustc_index = { version = "0.35.0", default-features = false } -ra-ap-rustc_abi = { version = "0.35.0", default-features = false } +ra-ap-rustc_lexer = { version = "0.40.0", default-features = false } +ra-ap-rustc_parse_format = { version = "0.40.0", default-features = false } +ra-ap-rustc_index = { version = "0.40.0", default-features = false } +ra-ap-rustc_abi = { version = "0.40.0", default-features = false } ra-ap-rustc_pattern_analysis = { version = "0.40.0", default-features = false } # local crates that aren't published to crates.io. These should not have versions. @@ -108,6 +108,7 @@ cargo_metadata = "0.18.1" command-group = "2.0.1" crossbeam-channel = "0.5.8" dissimilar = "1.0.7" +dot = "0.1.4" either = "1.9.0" expect-test = "1.4.0" hashbrown = { version = "0.14", features = [ @@ -117,6 +118,16 @@ indexmap = "2.1.0" itertools = "0.12.0" libc = "0.2.150" nohash-hasher = "0.2.0" +oorandom = "11.1.3" +object = { version = "0.33.0", default-features = false, features = [ + "std", + "read_core", + "elf", + "macho", + "pe", +] } +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" semver = "1.0.14" @@ -137,6 +148,7 @@ tracing-subscriber = { version = "0.3.18", default-features = false, features = "tracing-log", ] } triomphe = { version = "0.1.10", default-features = false, features = ["std"] } +url = "2.3.1" xshell = "0.2.5" diff --git a/crates/ide-db/src/prime_caches.rs b/crates/ide-db/src/prime_caches.rs index ef15f585fa2d..024e8f6ae39d 100644 --- a/crates/ide-db/src/prime_caches.rs +++ b/crates/ide-db/src/prime_caches.rs @@ -129,7 +129,7 @@ pub fn parallel_prime_caches( crates_currently_indexing.insert(crate_id, crate_name); } ParallelPrimeCacheWorkerProgress::EndCrate { crate_id } => { - crates_currently_indexing.remove(&crate_id); + crates_currently_indexing.swap_remove(&crate_id); crates_to_prime.mark_done(crate_id); crates_done += 1; } diff --git a/crates/ide/Cargo.toml b/crates/ide/Cargo.toml index eab3925aab65..006fd222c616 100644 --- a/crates/ide/Cargo.toml +++ b/crates/ide/Cargo.toml @@ -17,11 +17,11 @@ arrayvec.workspace = true either.workspace = true itertools.workspace = true tracing.workspace = true -oorandom = "11.1.3" -pulldown-cmark-to-cmark = "10.0.4" -pulldown-cmark = { version = "0.9.1", default-features = false } -url = "2.3.1" -dot = "0.1.4" +oorandom.workspace = true +pulldown-cmark-to-cmark.workspace = true +pulldown-cmark.workspace = true +url.workspace = true +dot.workspace = true smallvec.workspace = true triomphe.workspace = true nohash-hasher.workspace = true diff --git a/crates/proc-macro-api/Cargo.toml b/crates/proc-macro-api/Cargo.toml index e98d70776c95..978ad155609d 100644 --- a/crates/proc-macro-api/Cargo.toml +++ b/crates/proc-macro-api/Cargo.toml @@ -12,13 +12,7 @@ rust-version.workspace = true doctest = false [dependencies] -object = { version = "0.32.0", default-features = false, features = [ - "std", - "read_core", - "elf", - "macho", - "pe", -] } +object.workspace = true serde.workspace = true serde_json = { workspace = true, features = ["unbounded_depth"] } tracing.workspace = true diff --git a/crates/proc-macro-srv/Cargo.toml b/crates/proc-macro-srv/Cargo.toml index bd7a31654584..f8db1c6a30b4 100644 --- a/crates/proc-macro-srv/Cargo.toml +++ b/crates/proc-macro-srv/Cargo.toml @@ -12,13 +12,7 @@ rust-version.workspace = true doctest = false [dependencies] -object = { version = "0.32.0", default-features = false, features = [ - "std", - "read_core", - "elf", - "macho", - "pe", -] } +object.workspace = true libloading = "0.8.0" memmap2 = "0.5.4" diff --git a/crates/salsa/Cargo.toml b/crates/salsa/Cargo.toml index 9eec21f6a15f..0d3e1197b5c6 100644 --- a/crates/salsa/Cargo.toml +++ b/crates/salsa/Cargo.toml @@ -28,7 +28,6 @@ salsa-macros = { version = "0.0.0", path = "salsa-macros" } [dev-dependencies] linked-hash-map = "0.5.6" rand = "0.8.5" -test-log = "0.2.14" expect-test = "1.4.0" dissimilar = "1.0.7" diff --git a/crates/salsa/src/runtime.rs b/crates/salsa/src/runtime.rs index a7d5a2457823..e11cabfe11ed 100644 --- a/crates/salsa/src/runtime.rs +++ b/crates/salsa/src/runtime.rs @@ -595,7 +595,7 @@ impl ActiveQuery { fn remove_cycle_participants(&mut self, cycle: &Cycle) { if let Some(my_dependencies) = &mut self.dependencies { for p in cycle.participant_keys() { - my_dependencies.remove(&p); + my_dependencies.swap_remove(&p); } } } diff --git a/crates/salsa/tests/cycles.rs b/crates/salsa/tests/cycles.rs index 00ca5332440e..2be167bd8d3b 100644 --- a/crates/salsa/tests/cycles.rs +++ b/crates/salsa/tests/cycles.rs @@ -2,7 +2,6 @@ use std::panic::UnwindSafe; use expect_test::expect; use salsa::{Durability, ParallelDatabase, Snapshot}; -use test_log::test; // Axes: // diff --git a/crates/salsa/tests/parallel/parallel_cycle_all_recover.rs b/crates/salsa/tests/parallel/parallel_cycle_all_recover.rs index cee51b4db75e..a13ae3418f20 100644 --- a/crates/salsa/tests/parallel/parallel_cycle_all_recover.rs +++ b/crates/salsa/tests/parallel/parallel_cycle_all_recover.rs @@ -4,7 +4,6 @@ use crate::setup::{Knobs, ParDatabaseImpl}; use salsa::ParallelDatabase; -use test_log::test; // Recover cycle test: // diff --git a/crates/salsa/tests/parallel/parallel_cycle_mid_recover.rs b/crates/salsa/tests/parallel/parallel_cycle_mid_recover.rs index f78c05c5593c..971fe7ab1207 100644 --- a/crates/salsa/tests/parallel/parallel_cycle_mid_recover.rs +++ b/crates/salsa/tests/parallel/parallel_cycle_mid_recover.rs @@ -4,7 +4,6 @@ use crate::setup::{Knobs, ParDatabaseImpl}; use salsa::ParallelDatabase; -use test_log::test; // Recover cycle test: // diff --git a/crates/salsa/tests/parallel/parallel_cycle_none_recover.rs b/crates/salsa/tests/parallel/parallel_cycle_none_recover.rs index 35fe3791182e..e94982f513c5 100644 --- a/crates/salsa/tests/parallel/parallel_cycle_none_recover.rs +++ b/crates/salsa/tests/parallel/parallel_cycle_none_recover.rs @@ -5,7 +5,6 @@ use crate::setup::{Knobs, ParDatabaseImpl}; use expect_test::expect; use salsa::ParallelDatabase; -use test_log::test; #[test] fn parallel_cycle_none_recover() { diff --git a/crates/salsa/tests/parallel/parallel_cycle_one_recovers.rs b/crates/salsa/tests/parallel/parallel_cycle_one_recovers.rs index 7d3944714aef..025fbf37477f 100644 --- a/crates/salsa/tests/parallel/parallel_cycle_one_recovers.rs +++ b/crates/salsa/tests/parallel/parallel_cycle_one_recovers.rs @@ -4,7 +4,6 @@ use crate::setup::{Knobs, ParDatabaseImpl}; use salsa::ParallelDatabase; -use test_log::test; // Recover cycle test: // From ece18fecfabdc3583a3f38436682296e652161a2 Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 5 Mar 2024 19:29:49 +0800 Subject: [PATCH 35/69] fix: resolve sub-patterns inside range pattern --- crates/hir-def/src/body/lower.rs | 12 +++--------- crates/hir-def/src/body/pretty.rs | 2 +- crates/hir-def/src/hir.rs | 2 +- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index c9300898b386..18a6c5c2cdc2 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -1413,16 +1413,10 @@ impl ExprCollector<'_> { ast::Pat::LiteralPat(it) => { Some(Box::new(LiteralOrConst::Literal(pat_literal_to_hir(it)?.0))) } - ast::Pat::IdentPat(p) => { - let name = - p.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); - Some(Box::new(LiteralOrConst::Const(name.into()))) + pat @ (ast::Pat::IdentPat(_) | ast::Pat::PathPat(_)) => { + let subpat = self.collect_pat(pat.clone(), binding_list); + Some(Box::new(LiteralOrConst::Const(subpat))) } - ast::Pat::PathPat(p) => p - .path() - .and_then(|path| self.expander.parse_path(self.db, path)) - .map(LiteralOrConst::Const) - .map(Box::new), _ => None, }) }; diff --git a/crates/hir-def/src/body/pretty.rs b/crates/hir-def/src/body/pretty.rs index cd14f7b855a8..b2aab55a6a89 100644 --- a/crates/hir-def/src/body/pretty.rs +++ b/crates/hir-def/src/body/pretty.rs @@ -635,7 +635,7 @@ impl Printer<'_> { fn print_literal_or_const(&mut self, literal_or_const: &LiteralOrConst) { match literal_or_const { LiteralOrConst::Literal(l) => self.print_literal(l), - LiteralOrConst::Const(c) => self.print_path(c), + LiteralOrConst::Const(c) => self.print_pat(*c), } } diff --git a/crates/hir-def/src/hir.rs b/crates/hir-def/src/hir.rs index 34b2910b4f5e..ac0caaf0dc89 100644 --- a/crates/hir-def/src/hir.rs +++ b/crates/hir-def/src/hir.rs @@ -101,7 +101,7 @@ pub enum Literal { /// Used in range patterns. pub enum LiteralOrConst { Literal(Literal), - Const(Path), + Const(PatId), } impl Literal { From 96a7c6ae3cc69ace6c2e77cc4a4c7f453c07998c Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 5 Mar 2024 19:30:41 +0800 Subject: [PATCH 36/69] fix: mir for range pattern --- crates/hir-ty/src/mir/lower.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index ed316f972689..577a01aee782 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -1364,10 +1364,14 @@ impl<'ctx> MirLowerCtx<'ctx> { match loc { LiteralOrConst::Literal(l) => self.lower_literal_to_operand(ty, l), LiteralOrConst::Const(c) => { - let unresolved_name = || MirLowerError::unresolved_path(self.db, c); + let c = match &self.body.pats[*c] { + Pat::Path(p) => p, + _ => not_supported!("only `char` and numeric types are allowed in range patterns"), + }; + let unresolved_name = || MirLowerError::unresolved_path(self.db, c.as_ref()); let resolver = self.owner.resolver(self.db.upcast()); let pr = resolver - .resolve_path_in_value_ns(self.db.upcast(), c) + .resolve_path_in_value_ns(self.db.upcast(), c.as_ref()) .ok_or_else(unresolved_name)?; match pr { ResolveValueResult::ValueNs(v, _) => { From 16995ceda94b68f2bf667e1f7eff022ea795de50 Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 5 Mar 2024 19:31:01 +0800 Subject: [PATCH 37/69] test: add tests for constants inside range pattern --- crates/ide/src/goto_definition.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index 41148db61460..aac01384cbdb 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs @@ -532,6 +532,24 @@ fn bar() { $0foo!() => {} } } +"#, + ); + } + + #[test] + fn goto_definition_works_for_consts_inside_range_pattern() { + check( + r#" +//- /lib.rs +const A: u32 = 0; + //^ + +fn bar(v: u32) { + match v { + 0..=$0A => {} + _ => {} + } +} "#, ); } From 9cc3a9cfc25ea36ceb0474011d51de4fc7d42f7a Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 5 Mar 2024 19:55:31 +0800 Subject: [PATCH 38/69] fix: formatting --- crates/hir-ty/src/mir/lower.rs | 4 +++- crates/ide/src/goto_definition.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 577a01aee782..d0f739e6ac66 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -1366,7 +1366,9 @@ impl<'ctx> MirLowerCtx<'ctx> { LiteralOrConst::Const(c) => { let c = match &self.body.pats[*c] { Pat::Path(p) => p, - _ => not_supported!("only `char` and numeric types are allowed in range patterns"), + _ => not_supported!( + "only `char` and numeric types are allowed in range patterns" + ), }; let unresolved_name = || MirLowerError::unresolved_path(self.db, c.as_ref()); let resolver = self.owner.resolver(self.db.upcast()); diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index aac01384cbdb..1bda15255dcd 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs @@ -536,7 +536,7 @@ fn bar() { ); } - #[test] + #[test] fn goto_definition_works_for_consts_inside_range_pattern() { check( r#" From b06726bebe82ab965068a33e122317f3e3d5c10b Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Tue, 5 Mar 2024 20:16:32 +0800 Subject: [PATCH 39/69] remove `ignore-hidden = false` --- .typos.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/.typos.toml b/.typos.toml index 98dbe3a5d9d3..c2e8b265218f 100644 --- a/.typos.toml +++ b/.typos.toml @@ -5,7 +5,6 @@ extend-exclude = [ "crates/parser/test_data/lexer/err/", "crates/project-model/test_data/", ] -ignore-hidden = false [default] extend-ignore-re = [ From 1afeea85ffa65d0b9c6cc784542ba1716cb721db Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Tue, 5 Mar 2024 16:01:01 +0100 Subject: [PATCH 40/69] Add `fn parent_fn()` accessors for `hir::Param` & `hir::SelfParam` --- crates/hir/src/lib.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 4872c47c31d0..ffdf169bbb58 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -2108,6 +2108,10 @@ pub struct Param { } impl Param { + pub fn parent_fn(&self) -> Function { + self.func + } + pub fn ty(&self) -> &Type { &self.ty } @@ -2172,6 +2176,10 @@ impl SelfParam { .map(|value| InFile { file_id, value }) } + pub fn parent_fn(&self) -> Function { + Function::from(self.func) + } + pub fn ty(&self, db: &dyn HirDatabase) -> Type { let substs = TyBuilder::placeholder_subst(db, self.func); let callable_sig = From bf141310f8602a679b8cc3d6318cb9ef5be61c89 Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Tue, 5 Mar 2024 16:02:22 +0100 Subject: [PATCH 41/69] Add `fn index()` accessor for `hir::Param` --- crates/hir/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index ffdf169bbb58..5eed7ecd5b21 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -2112,6 +2112,10 @@ impl Param { self.func } + pub fn index(&self) -> usize { + self.idx + } + pub fn ty(&self) -> &Type { &self.ty } From 44be2432f50be8d7476f65b18220027110d7bd99 Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Fri, 1 Mar 2024 13:40:29 +0330 Subject: [PATCH 42/69] Add test explorer --- Cargo.toml | 1 + crates/flycheck/src/command.rs | 156 ++++++++++++++ crates/flycheck/src/lib.rs | 201 ++++-------------- crates/flycheck/src/test_runner.rs | 75 +++++++ crates/ide/src/lib.rs | 14 ++ crates/ide/src/test_explorer.rs | 135 ++++++++++++ crates/rust-analyzer/src/global_state.rs | 5 + .../src/hack_recover_crate_name.rs | 25 +++ .../src/handlers/notification.rs | 9 +- crates/rust-analyzer/src/handlers/request.rs | 65 ++++++ crates/rust-analyzer/src/lib.rs | 1 + crates/rust-analyzer/src/lsp/ext.rs | 102 +++++++++ crates/rust-analyzer/src/lsp/to_proto.rs | 26 +++ crates/rust-analyzer/src/main_loop.rs | 115 +++++++++- crates/stdx/src/process.rs | 5 + docs/dev/lsp-extensions.md | 102 ++++++++- editors/code/src/ctx.ts | 10 +- editors/code/src/lsp_ext.ts | 31 +++ editors/code/src/test_explorer.ts | 169 +++++++++++++++ 19 files changed, 1079 insertions(+), 168 deletions(-) create mode 100644 crates/flycheck/src/command.rs create mode 100644 crates/flycheck/src/test_runner.rs create mode 100644 crates/ide/src/test_explorer.rs create mode 100644 crates/rust-analyzer/src/hack_recover_crate_name.rs create mode 100644 editors/code/src/test_explorer.ts diff --git a/Cargo.toml b/Cargo.toml index e8e82914c7c4..eb3be72396c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -158,6 +158,7 @@ dashmap = { version = "=5.5.3", features = ["raw-api"] } [workspace.lints.rust] rust_2018_idioms = "warn" unused_lifetimes = "warn" +unreachable_pub = "warn" semicolon_in_expressions_from_macros = "warn" [workspace.lints.clippy] diff --git a/crates/flycheck/src/command.rs b/crates/flycheck/src/command.rs new file mode 100644 index 000000000000..091146a0010a --- /dev/null +++ b/crates/flycheck/src/command.rs @@ -0,0 +1,156 @@ +//! Utilities for running a cargo command like `cargo check` or `cargo test` in a separate thread and +//! parse its stdout/stderr. + +use std::{ + ffi::OsString, + fmt, io, + path::PathBuf, + process::{ChildStderr, ChildStdout, Command, Stdio}, +}; + +use command_group::{CommandGroup, GroupChild}; +use crossbeam_channel::{unbounded, Receiver, Sender}; +use stdx::process::streaming_output; + +/// Cargo output is structured as a one JSON per line. This trait abstracts parsing one line of +/// cargo output into a Rust data type. +pub(crate) trait ParseFromLine: Sized + Send + 'static { + fn from_line(line: &str, error: &mut String) -> Option; + fn from_eof() -> Option; +} + +struct CargoActor { + sender: Sender, + stdout: ChildStdout, + stderr: ChildStderr, +} + +impl CargoActor { + fn new(sender: Sender, stdout: ChildStdout, stderr: ChildStderr) -> Self { + CargoActor { sender, stdout, stderr } + } + + fn run(self) -> io::Result<(bool, String)> { + // We manually read a line at a time, instead of using serde's + // stream deserializers, because the deserializer cannot recover + // from an error, resulting in it getting stuck, because we try to + // be resilient against failures. + // + // Because cargo only outputs one JSON object per line, we can + // simply skip a line if it doesn't parse, which just ignores any + // erroneous output. + + let mut stdout_errors = String::new(); + let mut stderr_errors = String::new(); + let mut read_at_least_one_stdout_message = false; + let mut read_at_least_one_stderr_message = false; + let process_line = |line: &str, error: &mut String| { + // Try to deserialize a message from Cargo or Rustc. + if let Some(t) = T::from_line(line, error) { + self.sender.send(t).unwrap(); + true + } else { + false + } + }; + let output = streaming_output( + self.stdout, + self.stderr, + &mut |line| { + if process_line(line, &mut stdout_errors) { + read_at_least_one_stdout_message = true; + } + }, + &mut |line| { + if process_line(line, &mut stderr_errors) { + read_at_least_one_stderr_message = true; + } + }, + &mut || { + if let Some(t) = T::from_eof() { + self.sender.send(t).unwrap(); + } + }, + ); + + let read_at_least_one_message = + read_at_least_one_stdout_message || read_at_least_one_stderr_message; + let mut error = stdout_errors; + error.push_str(&stderr_errors); + match output { + Ok(_) => Ok((read_at_least_one_message, error)), + Err(e) => Err(io::Error::new(e.kind(), format!("{e:?}: {error}"))), + } + } +} + +struct JodGroupChild(GroupChild); + +impl Drop for JodGroupChild { + fn drop(&mut self) { + _ = self.0.kill(); + _ = self.0.wait(); + } +} + +/// A handle to a cargo process used for fly-checking. +pub(crate) struct CommandHandle { + /// The handle to the actual cargo process. As we cannot cancel directly from with + /// a read syscall dropping and therefore terminating the process is our best option. + child: JodGroupChild, + thread: stdx::thread::JoinHandle>, + pub(crate) receiver: Receiver, + program: OsString, + arguments: Vec, + current_dir: Option, +} + +impl fmt::Debug for CommandHandle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("CommandHandle") + .field("program", &self.program) + .field("arguments", &self.arguments) + .field("current_dir", &self.current_dir) + .finish() + } +} + +impl CommandHandle { + pub(crate) fn spawn(mut command: Command) -> std::io::Result { + command.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null()); + let mut child = command.group_spawn().map(JodGroupChild)?; + + let program = command.get_program().into(); + let arguments = command.get_args().map(|arg| arg.into()).collect::>(); + let current_dir = command.get_current_dir().map(|arg| arg.to_path_buf()); + + let stdout = child.0.inner().stdout.take().unwrap(); + let stderr = child.0.inner().stderr.take().unwrap(); + + let (sender, receiver) = unbounded(); + let actor = CargoActor::::new(sender, stdout, stderr); + let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker) + .name("CommandHandle".to_owned()) + .spawn(move || actor.run()) + .expect("failed to spawn thread"); + Ok(CommandHandle { program, arguments, current_dir, child, thread, receiver }) + } + + pub(crate) fn cancel(mut self) { + let _ = self.child.0.kill(); + let _ = self.child.0.wait(); + } + + pub(crate) fn join(mut self) -> io::Result<()> { + let _ = self.child.0.kill(); + let exit_status = self.child.0.wait()?; + let (read_at_least_one_message, error) = self.thread.join()?; + if read_at_least_one_message || exit_status.success() { + Ok(()) + } else { + Err(io::Error::new(io::ErrorKind::Other, format!( + "Cargo watcher failed, the command produced no valid metadata (exit code: {exit_status:?}):\n{error}" + ))) + } + } +} diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index 8bcdca5bb828..f8efb5202220 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs @@ -2,22 +2,18 @@ //! another compatible command (f.x. clippy) in a background thread and provide //! LSP diagnostics based on the output of the command. +// FIXME: This crate now handles running `cargo test` needed in the test explorer in +// addition to `cargo check`. Either split it into 3 crates (one for test, one for check +// and one common utilities) or change its name and docs to reflect the current state. + #![warn(rust_2018_idioms, unused_lifetimes)] -use std::{ - ffi::OsString, - fmt, io, - path::PathBuf, - process::{ChildStderr, ChildStdout, Command, Stdio}, - time::Duration, -}; +use std::{fmt, io, path::PathBuf, process::Command, time::Duration}; -use command_group::{CommandGroup, GroupChild}; use crossbeam_channel::{never, select, unbounded, Receiver, Sender}; use paths::{AbsPath, AbsPathBuf}; use rustc_hash::FxHashMap; use serde::Deserialize; -use stdx::process::streaming_output; pub use cargo_metadata::diagnostic::{ Applicability, Diagnostic, DiagnosticCode, DiagnosticLevel, DiagnosticSpan, @@ -25,6 +21,12 @@ pub use cargo_metadata::diagnostic::{ }; use toolchain::Tool; +mod command; +mod test_runner; + +use command::{CommandHandle, ParseFromLine}; +pub use test_runner::{CargoTestHandle, CargoTestMessage, TestState}; + #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] pub enum InvocationStrategy { Once, @@ -181,12 +183,12 @@ struct FlycheckActor { /// doesn't provide a way to read sub-process output without blocking, so we /// have to wrap sub-processes output handling in a thread and pass messages /// back over a channel. - command_handle: Option, + command_handle: Option>, } enum Event { RequestStateChange(StateChange), - CheckEvent(Option), + CheckEvent(Option), } const SAVED_FILE_PLACEHOLDER: &str = "$saved_file"; @@ -282,7 +284,7 @@ impl FlycheckActor { self.report_progress(Progress::DidFinish(res)); } Event::CheckEvent(Some(message)) => match message { - CargoMessage::CompilerArtifact(msg) => { + CargoCheckMessage::CompilerArtifact(msg) => { tracing::trace!( flycheck_id = self.id, artifact = msg.target.name, @@ -291,7 +293,7 @@ impl FlycheckActor { self.report_progress(Progress::DidCheckCrate(msg.target.name)); } - CargoMessage::Diagnostic(msg) => { + CargoCheckMessage::Diagnostic(msg) => { tracing::trace!( flycheck_id = self.id, message = msg.message, @@ -448,161 +450,42 @@ impl FlycheckActor { } } -struct JodGroupChild(GroupChild); - -impl Drop for JodGroupChild { - fn drop(&mut self) { - _ = self.0.kill(); - _ = self.0.wait(); - } -} - -/// A handle to a cargo process used for fly-checking. -struct CommandHandle { - /// The handle to the actual cargo process. As we cannot cancel directly from with - /// a read syscall dropping and therefore terminating the process is our best option. - child: JodGroupChild, - thread: stdx::thread::JoinHandle>, - receiver: Receiver, - program: OsString, - arguments: Vec, - current_dir: Option, -} - -impl fmt::Debug for CommandHandle { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("CommandHandle") - .field("program", &self.program) - .field("arguments", &self.arguments) - .field("current_dir", &self.current_dir) - .finish() - } +#[allow(clippy::large_enum_variant)] +enum CargoCheckMessage { + CompilerArtifact(cargo_metadata::Artifact), + Diagnostic(Diagnostic), } -impl CommandHandle { - fn spawn(mut command: Command) -> std::io::Result { - command.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null()); - let mut child = command.group_spawn().map(JodGroupChild)?; - - let program = command.get_program().into(); - let arguments = command.get_args().map(|arg| arg.into()).collect::>(); - let current_dir = command.get_current_dir().map(|arg| arg.to_path_buf()); - - let stdout = child.0.inner().stdout.take().unwrap(); - let stderr = child.0.inner().stderr.take().unwrap(); - - let (sender, receiver) = unbounded(); - let actor = CargoActor::new(sender, stdout, stderr); - let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker) - .name("CommandHandle".to_owned()) - .spawn(move || actor.run()) - .expect("failed to spawn thread"); - Ok(CommandHandle { program, arguments, current_dir, child, thread, receiver }) - } - - fn cancel(mut self) { - let _ = self.child.0.kill(); - let _ = self.child.0.wait(); - } - - fn join(mut self) -> io::Result<()> { - let _ = self.child.0.kill(); - let exit_status = self.child.0.wait()?; - let (read_at_least_one_message, error) = self.thread.join()?; - if read_at_least_one_message || exit_status.success() { - Ok(()) - } else { - Err(io::Error::new(io::ErrorKind::Other, format!( - "Cargo watcher failed, the command produced no valid metadata (exit code: {exit_status:?}):\n{error}" - ))) +impl ParseFromLine for CargoCheckMessage { + fn from_line(line: &str, error: &mut String) -> Option { + let mut deserializer = serde_json::Deserializer::from_str(line); + deserializer.disable_recursion_limit(); + if let Ok(message) = JsonMessage::deserialize(&mut deserializer) { + return match message { + // Skip certain kinds of messages to only spend time on what's useful + JsonMessage::Cargo(message) => match message { + cargo_metadata::Message::CompilerArtifact(artifact) if !artifact.fresh => { + Some(CargoCheckMessage::CompilerArtifact(artifact)) + } + cargo_metadata::Message::CompilerMessage(msg) => { + Some(CargoCheckMessage::Diagnostic(msg.message)) + } + _ => None, + }, + JsonMessage::Rustc(message) => Some(CargoCheckMessage::Diagnostic(message)), + }; } - } -} -struct CargoActor { - sender: Sender, - stdout: ChildStdout, - stderr: ChildStderr, -} - -impl CargoActor { - fn new(sender: Sender, stdout: ChildStdout, stderr: ChildStderr) -> CargoActor { - CargoActor { sender, stdout, stderr } + error.push_str(line); + error.push('\n'); + None } - fn run(self) -> io::Result<(bool, String)> { - // We manually read a line at a time, instead of using serde's - // stream deserializers, because the deserializer cannot recover - // from an error, resulting in it getting stuck, because we try to - // be resilient against failures. - // - // Because cargo only outputs one JSON object per line, we can - // simply skip a line if it doesn't parse, which just ignores any - // erroneous output. - - let mut stdout_errors = String::new(); - let mut stderr_errors = String::new(); - let mut read_at_least_one_stdout_message = false; - let mut read_at_least_one_stderr_message = false; - let process_line = |line: &str, error: &mut String| { - // Try to deserialize a message from Cargo or Rustc. - let mut deserializer = serde_json::Deserializer::from_str(line); - deserializer.disable_recursion_limit(); - if let Ok(message) = JsonMessage::deserialize(&mut deserializer) { - match message { - // Skip certain kinds of messages to only spend time on what's useful - JsonMessage::Cargo(message) => match message { - cargo_metadata::Message::CompilerArtifact(artifact) if !artifact.fresh => { - self.sender.send(CargoMessage::CompilerArtifact(artifact)).unwrap(); - } - cargo_metadata::Message::CompilerMessage(msg) => { - self.sender.send(CargoMessage::Diagnostic(msg.message)).unwrap(); - } - _ => (), - }, - JsonMessage::Rustc(message) => { - self.sender.send(CargoMessage::Diagnostic(message)).unwrap(); - } - } - return true; - } - - error.push_str(line); - error.push('\n'); - false - }; - let output = streaming_output( - self.stdout, - self.stderr, - &mut |line| { - if process_line(line, &mut stdout_errors) { - read_at_least_one_stdout_message = true; - } - }, - &mut |line| { - if process_line(line, &mut stderr_errors) { - read_at_least_one_stderr_message = true; - } - }, - ); - - let read_at_least_one_message = - read_at_least_one_stdout_message || read_at_least_one_stderr_message; - let mut error = stdout_errors; - error.push_str(&stderr_errors); - match output { - Ok(_) => Ok((read_at_least_one_message, error)), - Err(e) => Err(io::Error::new(e.kind(), format!("{e:?}: {error}"))), - } + fn from_eof() -> Option { + None } } -#[allow(clippy::large_enum_variant)] -enum CargoMessage { - CompilerArtifact(cargo_metadata::Artifact), - Diagnostic(Diagnostic), -} - #[derive(Deserialize)] #[serde(untagged)] enum JsonMessage { diff --git a/crates/flycheck/src/test_runner.rs b/crates/flycheck/src/test_runner.rs new file mode 100644 index 000000000000..b7d966989b9b --- /dev/null +++ b/crates/flycheck/src/test_runner.rs @@ -0,0 +1,75 @@ +//! This module provides the functionality needed to run `cargo test` in a background +//! thread and report the result of each test in a channel. + +use std::process::Command; + +use crossbeam_channel::Receiver; +use serde::Deserialize; +use toolchain::Tool; + +use crate::command::{CommandHandle, ParseFromLine}; + +#[derive(Debug, Deserialize)] +#[serde(tag = "event", rename_all = "camelCase")] +pub enum TestState { + Started, + Ok, + Failed { stdout: String }, +} + +#[derive(Debug, Deserialize)] +#[serde(tag = "type", rename_all = "camelCase")] +pub enum CargoTestMessage { + Test { + name: String, + #[serde(flatten)] + state: TestState, + }, + Suite, + Finished, +} + +impl ParseFromLine for CargoTestMessage { + fn from_line(line: &str, error: &mut String) -> Option { + let mut deserializer = serde_json::Deserializer::from_str(line); + deserializer.disable_recursion_limit(); + if let Ok(message) = CargoTestMessage::deserialize(&mut deserializer) { + return Some(message); + } + + error.push_str(line); + error.push('\n'); + None + } + + fn from_eof() -> Option { + Some(CargoTestMessage::Finished) + } +} + +#[derive(Debug)] +pub struct CargoTestHandle { + handle: CommandHandle, +} + +// Example of a cargo test command: +// cargo test -- module::func -Z unstable-options --format=json + +impl CargoTestHandle { + pub fn new(path: Option<&str>) -> std::io::Result { + let mut cmd = Command::new(Tool::Cargo.path()); + cmd.env("RUSTC_BOOTSTRAP", "1"); + cmd.arg("test"); + cmd.arg("--"); + if let Some(path) = path { + cmd.arg(path); + } + cmd.args(["-Z", "unstable-options"]); + cmd.arg("--format=json"); + Ok(Self { handle: CommandHandle::spawn(cmd)? }) + } + + pub fn receiver(&self) -> &Receiver { + &self.handle.receiver + } +} diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 4eb4acdf183c..59a7df14fd53 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -50,6 +50,7 @@ mod static_index; mod status; mod syntax_highlighting; mod syntax_tree; +mod test_explorer; mod typing; mod view_crate_graph; mod view_hir; @@ -108,6 +109,7 @@ pub use crate::{ tags::{Highlight, HlMod, HlMods, HlOperator, HlPunct, HlTag}, HighlightConfig, HlRange, }, + test_explorer::{TestItem, TestItemKind}, }; pub use hir::Semantics; pub use ide_assists::{ @@ -340,6 +342,18 @@ impl Analysis { self.with_db(|db| view_item_tree::view_item_tree(db, file_id)) } + pub fn discover_test_roots(&self) -> Cancellable> { + self.with_db(test_explorer::discover_test_roots) + } + + pub fn discover_tests_in_crate_by_test_id(&self, crate_id: &str) -> Cancellable> { + self.with_db(|db| test_explorer::discover_tests_in_crate_by_test_id(db, crate_id)) + } + + pub fn discover_tests_in_crate(&self, crate_id: CrateId) -> Cancellable> { + self.with_db(|db| test_explorer::discover_tests_in_crate(db, crate_id)) + } + /// Renders the crate graph to GraphViz "dot" syntax. pub fn view_crate_graph(&self, full: bool) -> Cancellable> { self.with_db(|db| view_crate_graph::view_crate_graph(db, full)) diff --git a/crates/ide/src/test_explorer.rs b/crates/ide/src/test_explorer.rs new file mode 100644 index 000000000000..2e741021ea8b --- /dev/null +++ b/crates/ide/src/test_explorer.rs @@ -0,0 +1,135 @@ +//! Discovers tests + +use hir::{Crate, Module, ModuleDef, Semantics}; +use ide_db::{ + base_db::{CrateGraph, CrateId, FileId, SourceDatabase}, + RootDatabase, +}; +use syntax::TextRange; + +use crate::{navigation_target::ToNav, runnables::runnable_fn, Runnable, TryToNav}; + +#[derive(Debug)] +pub enum TestItemKind { + Crate, + Module, + Function, +} + +#[derive(Debug)] +pub struct TestItem { + pub id: String, + pub kind: TestItemKind, + pub label: String, + pub parent: Option, + pub file: Option, + pub text_range: Option, + pub runnable: Option, +} + +pub(crate) fn discover_test_roots(db: &RootDatabase) -> Vec { + let crate_graph = db.crate_graph(); + crate_graph + .iter() + .filter(|&id| crate_graph[id].origin.is_local()) + .filter_map(|id| Some(crate_graph[id].display_name.as_ref()?.to_string())) + .map(|id| TestItem { + kind: TestItemKind::Crate, + label: id.clone(), + id, + parent: None, + file: None, + text_range: None, + runnable: None, + }) + .collect() +} + +fn find_crate_by_id(crate_graph: &CrateGraph, crate_id: &str) -> Option { + // here, we use display_name as the crate id. This is not super ideal, but it works since we + // only show tests for the local crates. + crate_graph.iter().find(|&id| { + crate_graph[id].origin.is_local() + && crate_graph[id].display_name.as_ref().is_some_and(|x| x.to_string() == crate_id) + }) +} + +fn discover_tests_in_module(db: &RootDatabase, module: Module, prefix_id: String) -> Vec { + let sema = Semantics::new(db); + + let mut r = vec![]; + for c in module.children(db) { + let module_name = + c.name(db).as_ref().and_then(|n| n.as_str()).unwrap_or("[mod without name]").to_owned(); + let module_id = format!("{prefix_id}::{module_name}"); + let module_children = discover_tests_in_module(db, c, module_id.clone()); + if !module_children.is_empty() { + let nav = c.to_nav(db).call_site; + r.push(TestItem { + id: module_id, + kind: TestItemKind::Module, + label: module_name, + parent: Some(prefix_id.clone()), + file: Some(nav.file_id), + text_range: Some(nav.focus_or_full_range()), + runnable: None, + }); + r.extend(module_children); + } + } + for def in module.declarations(db) { + let ModuleDef::Function(f) = def else { + continue; + }; + if !f.is_test(db) { + continue; + } + let nav = f.try_to_nav(db).map(|r| r.call_site); + let fn_name = f.name(db).as_str().unwrap_or("[function without name]").to_owned(); + r.push(TestItem { + id: format!("{prefix_id}::{fn_name}"), + kind: TestItemKind::Function, + label: fn_name, + parent: Some(prefix_id.clone()), + file: nav.as_ref().map(|n| n.file_id), + text_range: nav.as_ref().map(|n| n.focus_or_full_range()), + runnable: runnable_fn(&sema, f), + }); + } + r +} + +pub(crate) fn discover_tests_in_crate_by_test_id( + db: &RootDatabase, + crate_test_id: &str, +) -> Vec { + let crate_graph = db.crate_graph(); + let Some(crate_id) = find_crate_by_id(&crate_graph, crate_test_id) else { + return vec![]; + }; + discover_tests_in_crate(db, crate_id) +} + +pub(crate) fn discover_tests_in_crate(db: &RootDatabase, crate_id: CrateId) -> Vec { + let crate_graph = db.crate_graph(); + if !crate_graph[crate_id].origin.is_local() { + return vec![]; + } + let Some(crate_test_id) = &crate_graph[crate_id].display_name else { + return vec![]; + }; + let crate_test_id = crate_test_id.to_string(); + let crate_id: Crate = crate_id.into(); + let module = crate_id.root_module(); + let mut r = vec![TestItem { + id: crate_test_id.clone(), + kind: TestItemKind::Crate, + label: crate_test_id.clone(), + parent: None, + file: None, + text_range: None, + runnable: None, + }]; + r.extend(discover_tests_in_module(db, module, crate_test_id)); + r +} diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index 8b8d0ebcb989..560410e3325d 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -83,6 +83,9 @@ pub(crate) struct GlobalState { pub(crate) flycheck_receiver: Receiver, pub(crate) last_flycheck_error: Option, + // Test explorer + pub(crate) test_run_session: Option, + // VFS pub(crate) loader: Handle, Receiver>, pub(crate) vfs: Arc)>>, @@ -212,6 +215,8 @@ impl GlobalState { flycheck_receiver, last_flycheck_error: None, + test_run_session: None, + vfs: Arc::new(RwLock::new((vfs::Vfs::default(), IntMap::default()))), vfs_config_version: 0, vfs_progress_config_version: 0, diff --git a/crates/rust-analyzer/src/hack_recover_crate_name.rs b/crates/rust-analyzer/src/hack_recover_crate_name.rs new file mode 100644 index 000000000000..d7285653c5fa --- /dev/null +++ b/crates/rust-analyzer/src/hack_recover_crate_name.rs @@ -0,0 +1,25 @@ +//! Currently cargo does not emit crate name in the `cargo test --format=json`, which needs to be changed. This +//! module contains a way to recover crate names in a very hacky and wrong way. + +// FIXME(hack_recover_crate_name): Remove this module. + +use std::sync::{Mutex, MutexGuard, OnceLock}; + +use ide_db::FxHashMap; + +static STORAGE: OnceLock>> = OnceLock::new(); + +fn get_storage() -> MutexGuard<'static, FxHashMap> { + STORAGE.get_or_init(|| Mutex::new(FxHashMap::default())).lock().unwrap() +} + +pub(crate) fn insert_name(name_with_crate: String) { + let Some((_, name_without_crate)) = name_with_crate.split_once("::") else { + return; + }; + get_storage().insert(name_without_crate.to_owned(), name_with_crate); +} + +pub(crate) fn lookup_name(name_without_crate: String) -> Option { + get_storage().get(&name_without_crate).cloned() +} diff --git a/crates/rust-analyzer/src/handlers/notification.rs b/crates/rust-analyzer/src/handlers/notification.rs index cf646a2e2828..ff213748b4ff 100644 --- a/crates/rust-analyzer/src/handlers/notification.rs +++ b/crates/rust-analyzer/src/handlers/notification.rs @@ -16,7 +16,7 @@ use crate::{ config::Config, global_state::GlobalState, lsp::{from_proto, utils::apply_document_changes}, - lsp_ext::RunFlycheckParams, + lsp_ext::{self, RunFlycheckParams}, mem_docs::DocumentData, reload, }; @@ -373,3 +373,10 @@ pub(crate) fn handle_run_flycheck( } Ok(()) } + +pub(crate) fn handle_abort_run_test(state: &mut GlobalState, _: ()) -> anyhow::Result<()> { + if state.test_run_session.take().is_some() { + state.send_notification::(()); + } + Ok(()) +} diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index 0e005975fbae..cc4333bd1dbd 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -39,6 +39,7 @@ use crate::{ config::{Config, RustfmtConfig, WorkspaceSymbolConfig}, diff::diff, global_state::{GlobalState, GlobalStateSnapshot}, + hack_recover_crate_name, line_index::LineEndings, lsp::{ from_proto, to_proto, @@ -192,6 +193,70 @@ pub(crate) fn handle_view_item_tree( Ok(res) } +pub(crate) fn handle_run_test( + state: &mut GlobalState, + params: lsp_ext::RunTestParams, +) -> anyhow::Result<()> { + if let Some(_session) = state.test_run_session.take() { + state.send_notification::(()); + } + // We detect the lowest common ansector of all included tests, and + // run it. We ignore excluded tests for now, the client will handle + // it for us. + let lca = match params.include { + Some(tests) => tests + .into_iter() + .reduce(|x, y| { + let mut common_prefix = "".to_owned(); + for (xc, yc) in x.chars().zip(y.chars()) { + if xc != yc { + break; + } + common_prefix.push(xc); + } + common_prefix + }) + .unwrap_or_default(), + None => "".to_owned(), + }; + let handle = if lca.is_empty() { + flycheck::CargoTestHandle::new(None) + } else if let Some((_, path)) = lca.split_once("::") { + flycheck::CargoTestHandle::new(Some(path)) + } else { + flycheck::CargoTestHandle::new(None) + }; + state.test_run_session = Some(handle?); + Ok(()) +} + +pub(crate) fn handle_discover_test( + snap: GlobalStateSnapshot, + params: lsp_ext::DiscoverTestParams, +) -> anyhow::Result { + let _p = tracing::span!(tracing::Level::INFO, "handle_discover_test").entered(); + let (tests, scope) = match params.test_id { + Some(id) => { + let crate_id = id.split_once("::").map(|it| it.0).unwrap_or(&id); + (snap.analysis.discover_tests_in_crate_by_test_id(crate_id)?, vec![crate_id.to_owned()]) + } + None => (snap.analysis.discover_test_roots()?, vec![]), + }; + for t in &tests { + hack_recover_crate_name::insert_name(t.id.clone()); + } + Ok(lsp_ext::DiscoverTestResults { + tests: tests + .into_iter() + .map(|t| { + let line_index = t.file.and_then(|f| snap.file_line_index(f).ok()); + to_proto::test_item(&snap, t, line_index.as_ref()) + }) + .collect(), + scope, + }) +} + pub(crate) fn handle_view_crate_graph( snap: GlobalStateSnapshot, params: ViewCrateGraphParams, diff --git a/crates/rust-analyzer/src/lib.rs b/crates/rust-analyzer/src/lib.rs index 473ca991ad9b..175ffa622ff7 100644 --- a/crates/rust-analyzer/src/lib.rs +++ b/crates/rust-analyzer/src/lib.rs @@ -19,6 +19,7 @@ mod diagnostics; mod diff; mod dispatch; mod global_state; +mod hack_recover_crate_name; mod line_index; mod main_loop; mod mem_docs; diff --git a/crates/rust-analyzer/src/lsp/ext.rs b/crates/rust-analyzer/src/lsp/ext.rs index aa40728ce6cb..842e765d9d15 100644 --- a/crates/rust-analyzer/src/lsp/ext.rs +++ b/crates/rust-analyzer/src/lsp/ext.rs @@ -163,6 +163,108 @@ impl Request for ViewItemTree { const METHOD: &'static str = "rust-analyzer/viewItemTree"; } +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct DiscoverTestParams { + pub test_id: Option, +} + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub enum TestItemIcon { + Package, + Module, + Test, +} + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct TestItem { + pub id: String, + pub label: String, + pub icon: TestItemIcon, + pub can_resolve_children: bool, + pub parent: Option, + pub text_document: Option, + pub range: Option, + pub runnable: Option, +} + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct DiscoverTestResults { + pub tests: Vec, + pub scope: Vec, +} + +pub enum DiscoverTest {} + +impl Request for DiscoverTest { + type Params = DiscoverTestParams; + type Result = DiscoverTestResults; + const METHOD: &'static str = "experimental/discoverTest"; +} + +pub enum DiscoveredTests {} + +impl Notification for DiscoveredTests { + type Params = DiscoverTestResults; + const METHOD: &'static str = "experimental/discoveredTests"; +} + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct RunTestParams { + pub include: Option>, + pub exclude: Option>, +} + +pub enum RunTest {} + +impl Request for RunTest { + type Params = RunTestParams; + type Result = (); + const METHOD: &'static str = "experimental/runTest"; +} + +pub enum EndRunTest {} + +impl Notification for EndRunTest { + type Params = (); + const METHOD: &'static str = "experimental/endRunTest"; +} + +pub enum AbortRunTest {} + +impl Notification for AbortRunTest { + type Params = (); + const METHOD: &'static str = "experimental/abortRunTest"; +} + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase", tag = "tag")] +pub enum TestState { + Passed, + Failed { message: String }, + Skipped, + Started, + Enqueued, +} + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct ChangeTestStateParams { + pub test_id: String, + pub state: TestState, +} + +pub enum ChangeTestState {} + +impl Notification for ChangeTestState { + type Params = ChangeTestStateParams; + const METHOD: &'static str = "experimental/changeTestState"; +} + pub enum ExpandMacro {} impl Request for ExpandMacro { diff --git a/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs index 481ebfefd4ee..f0bb7d8af3ab 100644 --- a/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/crates/rust-analyzer/src/lsp/to_proto.rs @@ -1498,6 +1498,32 @@ pub(crate) fn code_lens( Ok(()) } +pub(crate) fn test_item( + snap: &GlobalStateSnapshot, + test_item: ide::TestItem, + line_index: Option<&LineIndex>, +) -> lsp_ext::TestItem { + lsp_ext::TestItem { + id: test_item.id, + label: test_item.label, + icon: match test_item.kind { + ide::TestItemKind::Crate => lsp_ext::TestItemIcon::Package, + ide::TestItemKind::Module => lsp_ext::TestItemIcon::Module, + ide::TestItemKind::Function => lsp_ext::TestItemIcon::Test, + }, + can_resolve_children: matches!( + test_item.kind, + ide::TestItemKind::Crate | ide::TestItemKind::Module + ), + parent: test_item.parent, + text_document: test_item + .file + .map(|f| lsp_types::TextDocumentIdentifier { uri: url(snap, f) }), + range: line_index.and_then(|l| Some(range(l, test_item.text_range?))), + runnable: test_item.runnable.and_then(|r| runnable(snap, r).ok()), + } +} + pub(crate) mod command { use ide::{FileRange, NavigationTarget}; use serde_json::to_value; diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 72f6d0fde5fe..87da95c87e32 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -1,14 +1,15 @@ //! The main loop of `rust-analyzer` responsible for dispatching LSP //! requests/replies and notifications back to the client. -use crate::lsp::ext; + use std::{ fmt, time::{Duration, Instant}, }; use always_assert::always; -use crossbeam_channel::{select, Receiver}; +use crossbeam_channel::{never, select, Receiver}; use ide_db::base_db::{SourceDatabase, SourceDatabaseExt, VfsPath}; +use itertools::Itertools; use lsp_server::{Connection, Notification, Request}; use lsp_types::notification::Notification as _; use stdx::thread::ThreadIntent; @@ -19,8 +20,9 @@ use crate::{ diagnostics::fetch_native_diagnostics, dispatch::{NotificationDispatcher, RequestDispatcher}, global_state::{file_id_to_url, url_to_file_id, GlobalState}, + hack_recover_crate_name, lsp::{ - from_proto, + from_proto, to_proto, utils::{notification_is, Progress}, }, lsp_ext, @@ -58,6 +60,7 @@ enum Event { QueuedTask(QueuedTask), Vfs(vfs::loader::Message), Flycheck(flycheck::Message), + TestResult(flycheck::CargoTestMessage), } impl fmt::Display for Event { @@ -68,6 +71,7 @@ impl fmt::Display for Event { Event::Vfs(_) => write!(f, "Event::Vfs"), Event::Flycheck(_) => write!(f, "Event::Flycheck"), Event::QueuedTask(_) => write!(f, "Event::QueuedTask"), + Event::TestResult(_) => write!(f, "Event::TestResult"), } } } @@ -81,9 +85,10 @@ pub(crate) enum QueuedTask { #[derive(Debug)] pub(crate) enum Task { Response(lsp_server::Response), - ClientNotification(ext::UnindexedProjectParams), + ClientNotification(lsp_ext::UnindexedProjectParams), Retry(lsp_server::Request), Diagnostics(Vec<(FileId, Vec)>), + DiscoverTest(lsp_ext::DiscoverTestResults), PrimeCaches(PrimeCachesProgress), FetchWorkspace(ProjectWorkspaceProgress), FetchBuildData(BuildDataProgress), @@ -127,6 +132,7 @@ impl fmt::Debug for Event { Event::QueuedTask(it) => fmt::Debug::fmt(it, f), Event::Vfs(it) => fmt::Debug::fmt(it, f), Event::Flycheck(it) => fmt::Debug::fmt(it, f), + Event::TestResult(it) => fmt::Debug::fmt(it, f), } } } @@ -214,6 +220,10 @@ impl GlobalState { recv(self.flycheck_receiver) -> task => Some(Event::Flycheck(task.unwrap())), + + recv(self.test_run_session.as_ref().map(|s| s.receiver()).unwrap_or(&never())) -> task => + Some(Event::TestResult(task.unwrap())), + } } @@ -322,6 +332,18 @@ impl GlobalState { self.handle_flycheck_msg(message); } } + Event::TestResult(message) => { + let _p = + tracing::span!(tracing::Level::INFO, "GlobalState::handle_event/test_result") + .entered(); + self.handle_cargo_test_msg(message); + // Coalesce many test result event into a single loop turn + while let Some(message) = + self.test_run_session.as_ref().and_then(|r| r.receiver().try_recv().ok()) + { + self.handle_cargo_test_msg(message); + } + } } let event_handling_duration = loop_start.elapsed(); @@ -367,7 +389,8 @@ impl GlobalState { let update_diagnostics = (!was_quiescent || state_changed || memdocs_added_or_removed) && self.config.publish_diagnostics(); if update_diagnostics { - self.update_diagnostics() + self.update_diagnostics(); + self.update_tests(); } } @@ -488,6 +511,55 @@ impl GlobalState { }); } + fn update_tests(&mut self) { + let db = self.analysis_host.raw_database(); + let subscriptions = self + .mem_docs + .iter() + .map(|path| self.vfs.read().0.file_id(path).unwrap()) + .filter(|&file_id| { + let source_root = db.file_source_root(file_id); + !db.source_root(source_root).is_library + }) + .collect::>(); + tracing::trace!("updating tests for {:?}", subscriptions); + + // Updating tests are triggered by the user typing + // so we run them on a latency sensitive thread. + self.task_pool.handle.spawn(ThreadIntent::LatencySensitive, { + let snapshot = self.snapshot(); + move || { + let tests = subscriptions + .into_iter() + .filter_map(|f| snapshot.analysis.crates_for(f).ok()) + .flatten() + .unique() + .filter_map(|c| snapshot.analysis.discover_tests_in_crate(c).ok()) + .flatten() + .collect::>(); + for t in &tests { + hack_recover_crate_name::insert_name(t.id.clone()); + } + let scope = tests + .iter() + .filter_map(|t| Some(t.id.split_once("::")?.0)) + .unique() + .map(|it| it.to_owned()) + .collect(); + Task::DiscoverTest(lsp_ext::DiscoverTestResults { + tests: tests + .into_iter() + .map(|t| { + let line_index = t.file.and_then(|f| snapshot.file_line_index(f).ok()); + to_proto::test_item(&snapshot, t, line_index.as_ref()) + }) + .collect(), + scope, + }) + } + }); + } + fn update_status_or_notify(&mut self) { let status = self.current_status(); if self.last_reported_status.as_ref() != Some(&status) { @@ -598,6 +670,9 @@ impl GlobalState { } } Task::BuildDepsHaveChanged => self.build_deps_changed = true, + Task::DiscoverTest(tests) => { + self.send_notification::(tests); + } } } @@ -666,7 +741,7 @@ impl GlobalState { let id = from_proto::file_id(&snap, &uri).expect("unable to get FileId"); if let Ok(crates) = &snap.analysis.crates_for(id) { if crates.is_empty() { - let params = ext::UnindexedProjectParams { + let params = lsp_ext::UnindexedProjectParams { text_documents: vec![lsp_types::TextDocumentIdentifier { uri }], }; sender.send(Task::ClientNotification(params)).unwrap(); @@ -698,6 +773,31 @@ impl GlobalState { } } + fn handle_cargo_test_msg(&mut self, message: flycheck::CargoTestMessage) { + match message { + flycheck::CargoTestMessage::Test { name, state } => { + let state = match state { + flycheck::TestState::Started => lsp_ext::TestState::Started, + flycheck::TestState::Ok => lsp_ext::TestState::Passed, + flycheck::TestState::Failed { stdout } => { + lsp_ext::TestState::Failed { message: stdout } + } + }; + let Some(test_id) = hack_recover_crate_name::lookup_name(name) else { + return; + }; + self.send_notification::( + lsp_ext::ChangeTestStateParams { test_id, state }, + ); + } + flycheck::CargoTestMessage::Suite => (), + flycheck::CargoTestMessage::Finished => { + self.send_notification::(()); + self.test_run_session = None; + } + } + } + fn handle_flycheck_msg(&mut self, message: flycheck::Message) { match message { flycheck::Message::AddDiagnostic { id, workspace_root, diagnostic } => { @@ -803,6 +903,7 @@ impl GlobalState { .on_sync_mut::(handlers::handle_proc_macros_rebuild) .on_sync_mut::(handlers::handle_memory_usage) .on_sync_mut::(handlers::handle_shuffle_crate_graph) + .on_sync_mut::(handlers::handle_run_test) // Request handlers which are related to the user typing // are run on the main thread to reduce latency: .on_sync::(handlers::handle_join_lines) @@ -843,6 +944,7 @@ impl GlobalState { .on::(handlers::handle_view_file_text) .on::(handlers::handle_view_crate_graph) .on::(handlers::handle_view_item_tree) + .on::(handlers::handle_discover_test) .on::(handlers::handle_expand_macro) .on::(handlers::handle_parent_module) .on::(handlers::handle_runnables) @@ -906,6 +1008,7 @@ impl GlobalState { .on_sync_mut::(handlers::handle_cancel_flycheck)? .on_sync_mut::(handlers::handle_clear_flycheck)? .on_sync_mut::(handlers::handle_run_flycheck)? + .on_sync_mut::(handlers::handle_abort_run_test)? .finish(); Ok(()) } diff --git a/crates/stdx/src/process.rs b/crates/stdx/src/process.rs index bca0cbc36d1a..e6935f06b2ce 100644 --- a/crates/stdx/src/process.rs +++ b/crates/stdx/src/process.rs @@ -15,6 +15,7 @@ pub fn streaming_output( err: ChildStderr, on_stdout_line: &mut dyn FnMut(&str), on_stderr_line: &mut dyn FnMut(&str), + on_eof: &mut dyn FnMut(), ) -> io::Result<(Vec, Vec)> { let mut stdout = Vec::new(); let mut stderr = Vec::new(); @@ -44,6 +45,9 @@ pub fn streaming_output( on_stderr_line(line); } } + if eof { + on_eof(); + } } })?; @@ -63,6 +67,7 @@ pub fn spawn_with_streaming_output( child.stderr.take().unwrap(), on_stdout_line, on_stderr_line, + &mut || (), )?; let status = child.wait()?; Ok(Output { status, stdout, stderr }) diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md index f3100ee194e6..8d523d7baa3e 100644 --- a/docs/dev/lsp-extensions.md +++ b/docs/dev/lsp-extensions.md @@ -1,5 +1,5 @@