From dadad36bb9770f9b13ed84bc219ea0168a7a5bf1 Mon Sep 17 00:00:00 2001 From: Emil Lauridsen Date: Mon, 18 Nov 2019 18:02:28 +0100 Subject: [PATCH 01/24] Move type inlay hint truncation to language server This commit implements a general truncation framework for HirFormatter that keeps track of how much has been output so far. This information can then be used to perform truncation inside the language server, instead of relying on the client. Initial support is implemented for truncating types hints using the maxInlayHintLength server config option. The existing solution in the VSCode extension has been removed in favor of letting the server truncate type hints. --- crates/ra_hir/src/ty.rs | 20 +++++++++ crates/ra_hir/src/ty/display.rs | 43 +++++++++++++++++-- crates/ra_ide_api/src/inlay_hints.rs | 37 +++++++++------- crates/ra_ide_api/src/lib.rs | 10 ++++- crates/ra_lsp_server/src/config.rs | 3 ++ crates/ra_lsp_server/src/main_loop.rs | 1 + .../ra_lsp_server/src/main_loop/handlers.rs | 2 +- crates/ra_lsp_server/src/world.rs | 1 + editors/code/src/commands/inlay_hints.ts | 14 +----- editors/code/src/server.ts | 1 + 10 files changed, 97 insertions(+), 35 deletions(-) diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index b7f50b714f..776613c7ce 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -800,6 +800,10 @@ impl HirDisplay for &Ty { impl HirDisplay for ApplicationTy { fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { + if f.should_truncate() { + return write!(f, "…"); + } + match self.ctor { TypeCtor::Bool => write!(f, "bool")?, TypeCtor::Char => write!(f, "char")?, @@ -901,6 +905,10 @@ impl HirDisplay for ApplicationTy { impl HirDisplay for ProjectionTy { fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { + if f.should_truncate() { + return write!(f, "…"); + } + let trait_name = self .associated_ty .parent_trait(f.db) @@ -919,6 +927,10 @@ impl HirDisplay for ProjectionTy { impl HirDisplay for Ty { fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { + if f.should_truncate() { + return write!(f, "…"); + } + match self { Ty::Apply(a_ty) => a_ty.hir_fmt(f)?, Ty::Projection(p_ty) => p_ty.hir_fmt(f)?, @@ -1001,6 +1013,10 @@ impl HirDisplay for Ty { impl TraitRef { fn hir_fmt_ext(&self, f: &mut HirFormatter, use_as: bool) -> fmt::Result { + if f.should_truncate() { + return write!(f, "…"); + } + self.substs[0].hir_fmt(f)?; if use_as { write!(f, " as ")?; @@ -1031,6 +1047,10 @@ impl HirDisplay for &GenericPredicate { impl HirDisplay for GenericPredicate { fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { + if f.should_truncate() { + return write!(f, "…"); + } + match self { GenericPredicate::Implemented(trait_ref) => trait_ref.hir_fmt(f)?, GenericPredicate::Projection(projection_pred) => { diff --git a/crates/ra_hir/src/ty/display.rs b/crates/ra_hir/src/ty/display.rs index 7910429d72..9bb3ece6c8 100644 --- a/crates/ra_hir/src/ty/display.rs +++ b/crates/ra_hir/src/ty/display.rs @@ -7,15 +7,30 @@ use crate::db::HirDatabase; pub struct HirFormatter<'a, 'b, DB> { pub db: &'a DB, fmt: &'a mut fmt::Formatter<'b>, + buf: String, + curr_size: usize, + max_size: Option, } pub trait HirDisplay { fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result; + fn display<'a, DB>(&'a self, db: &'a DB) -> HirDisplayWrapper<'a, DB, Self> where Self: Sized, { - HirDisplayWrapper(db, self) + HirDisplayWrapper(db, self, None) + } + + fn display_truncated<'a, DB>( + &'a self, + db: &'a DB, + max_size: Option, + ) -> HirDisplayWrapper<'a, DB, Self> + where + Self: Sized, + { + HirDisplayWrapper(db, self, max_size) } } @@ -41,11 +56,25 @@ where /// This allows using the `write!` macro directly with a `HirFormatter`. pub fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result { - fmt::write(self.fmt, args) + // We write to a buffer first to track output size + self.buf.clear(); + fmt::write(&mut self.buf, args)?; + self.curr_size += self.buf.len(); + + // Then we write to the internal formatter from the buffer + self.fmt.write_str(&self.buf) + } + + pub fn should_truncate(&self) -> bool { + if let Some(max_size) = self.max_size { + self.curr_size >= max_size + } else { + false + } } } -pub struct HirDisplayWrapper<'a, DB, T>(&'a DB, &'a T); +pub struct HirDisplayWrapper<'a, DB, T>(&'a DB, &'a T, Option); impl<'a, DB, T> fmt::Display for HirDisplayWrapper<'a, DB, T> where @@ -53,6 +82,12 @@ where T: HirDisplay, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.1.hir_fmt(&mut HirFormatter { db: self.0, fmt: f }) + self.1.hir_fmt(&mut HirFormatter { + db: self.0, + fmt: f, + buf: String::with_capacity(20), + curr_size: 0, + max_size: self.2, + }) } } diff --git a/crates/ra_ide_api/src/inlay_hints.rs b/crates/ra_ide_api/src/inlay_hints.rs index 0cd9598483..6cd492b2a0 100644 --- a/crates/ra_ide_api/src/inlay_hints.rs +++ b/crates/ra_ide_api/src/inlay_hints.rs @@ -19,10 +19,15 @@ pub struct InlayHint { pub label: SmolStr, } -pub(crate) fn inlay_hints(db: &RootDatabase, file_id: FileId, file: &SourceFile) -> Vec { +pub(crate) fn inlay_hints( + db: &RootDatabase, + file_id: FileId, + file: &SourceFile, + max_inlay_hint_length: Option, +) -> Vec { file.syntax() .descendants() - .map(|node| get_inlay_hints(db, file_id, &node).unwrap_or_default()) + .map(|node| get_inlay_hints(db, file_id, &node, max_inlay_hint_length).unwrap_or_default()) .flatten() .collect() } @@ -31,6 +36,7 @@ fn get_inlay_hints( db: &RootDatabase, file_id: FileId, node: &SyntaxNode, + max_inlay_hint_length: Option, ) -> Option> { let analyzer = SourceAnalyzer::new(db, hir::Source::new(file_id.into(), node), None); match_ast! { @@ -40,7 +46,7 @@ fn get_inlay_hints( return None; } let pat = it.pat()?; - Some(get_pat_type_hints(db, &analyzer, pat, false)) + Some(get_pat_type_hints(db, &analyzer, pat, false, max_inlay_hint_length)) }, ast::LambdaExpr(it) => { it.param_list().map(|param_list| { @@ -48,22 +54,22 @@ fn get_inlay_hints( .params() .filter(|closure_param| closure_param.ascribed_type().is_none()) .filter_map(|closure_param| closure_param.pat()) - .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, false)) + .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, false, max_inlay_hint_length)) .flatten() .collect() }) }, ast::ForExpr(it) => { let pat = it.pat()?; - Some(get_pat_type_hints(db, &analyzer, pat, false)) + Some(get_pat_type_hints(db, &analyzer, pat, false, max_inlay_hint_length)) }, ast::IfExpr(it) => { let pat = it.condition()?.pat()?; - Some(get_pat_type_hints(db, &analyzer, pat, true)) + Some(get_pat_type_hints(db, &analyzer, pat, true, max_inlay_hint_length)) }, ast::WhileExpr(it) => { let pat = it.condition()?.pat()?; - Some(get_pat_type_hints(db, &analyzer, pat, true)) + Some(get_pat_type_hints(db, &analyzer, pat, true, max_inlay_hint_length)) }, ast::MatchArmList(it) => { Some( @@ -71,7 +77,7 @@ fn get_inlay_hints( .arms() .map(|match_arm| match_arm.pats()) .flatten() - .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, true)) + .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, true, max_inlay_hint_length)) .flatten() .collect(), ) @@ -86,6 +92,7 @@ fn get_pat_type_hints( analyzer: &SourceAnalyzer, root_pat: ast::Pat, skip_root_pat_hint: bool, + max_inlay_hint_length: Option, ) -> Vec { let original_pat = &root_pat.clone(); @@ -99,7 +106,7 @@ fn get_pat_type_hints( .map(|(range, pat_type)| InlayHint { range, kind: InlayKind::TypeHint, - label: pat_type.display(db).to_string().into(), + label: pat_type.display_truncated(db, max_inlay_hint_length).to_string().into(), }) .collect() } @@ -209,7 +216,7 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" [ InlayHint { range: [193; 197), @@ -278,7 +285,7 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" [ InlayHint { range: [21; 30), @@ -307,7 +314,7 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" [ InlayHint { range: [21; 30), @@ -355,7 +362,7 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" [ InlayHint { range: [166; 170), @@ -418,7 +425,7 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" [ InlayHint { range: [166; 170), @@ -481,7 +488,7 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" [ InlayHint { range: [311; 315), diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs index 110ddcd626..fcb3da90e4 100644 --- a/crates/ra_ide_api/src/lib.rs +++ b/crates/ra_ide_api/src/lib.rs @@ -338,8 +338,14 @@ impl Analysis { } /// Returns a list of the places in the file where type hints can be displayed. - pub fn inlay_hints(&self, file_id: FileId) -> Cancelable> { - self.with_db(|db| inlay_hints::inlay_hints(db, file_id, &db.parse(file_id).tree())) + pub fn inlay_hints( + &self, + file_id: FileId, + max_inlay_hint_length: Option, + ) -> Cancelable> { + self.with_db(|db| { + inlay_hints::inlay_hints(db, file_id, &db.parse(file_id).tree(), max_inlay_hint_length) + }) } /// Returns the set of folding ranges. diff --git a/crates/ra_lsp_server/src/config.rs b/crates/ra_lsp_server/src/config.rs index 9871a3b37f..8045f3d60d 100644 --- a/crates/ra_lsp_server/src/config.rs +++ b/crates/ra_lsp_server/src/config.rs @@ -29,6 +29,8 @@ pub struct ServerConfig { pub lru_capacity: Option, + pub max_inlay_hint_length: Option, + /// For internal usage to make integrated tests faster. #[serde(deserialize_with = "nullable_bool_true")] pub with_sysroot: bool, @@ -44,6 +46,7 @@ impl Default for ServerConfig { exclude_globs: Vec::new(), use_client_watching: false, lru_capacity: None, + max_inlay_hint_length: None, with_sysroot: true, feature_flags: FxHashMap::default(), } diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 379dab4384..3e2ac36830 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs @@ -123,6 +123,7 @@ pub fn main_loop( .and_then(|it| it.folding_range.as_ref()) .and_then(|it| it.line_folding_only) .unwrap_or(false), + max_inlay_hint_length: config.max_inlay_hint_length, } }; diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 20f9aee138..7347a78c7a 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -870,7 +870,7 @@ pub fn handle_inlay_hints( let analysis = world.analysis(); let line_index = analysis.file_line_index(file_id)?; Ok(analysis - .inlay_hints(file_id)? + .inlay_hints(file_id, world.options.max_inlay_hint_length)? .into_iter() .map(|api_type| InlayHint { label: api_type.label.to_string(), diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index 51824e7a35..9bdea70c74 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs @@ -28,6 +28,7 @@ pub struct Options { pub publish_decorations: bool, pub supports_location_link: bool, pub line_folding_only: bool, + pub max_inlay_hint_length: Option, } /// `WorldState` is the primary mutable state of the language server diff --git a/editors/code/src/commands/inlay_hints.ts b/editors/code/src/commands/inlay_hints.ts index ffaaaebcb0..0dbdd94fba 100644 --- a/editors/code/src/commands/inlay_hints.ts +++ b/editors/code/src/commands/inlay_hints.ts @@ -87,7 +87,7 @@ export class HintsUpdater { range: hint.range, renderOptions: { after: { - contentText: `: ${this.truncateHint(hint.label)}` + contentText: `: ${hint.label}` } } })); @@ -98,18 +98,6 @@ export class HintsUpdater { } } - private truncateHint(label: string): string { - if (!Server.config.maxInlayHintLength) { - return label; - } - - let newLabel = label.substring(0, Server.config.maxInlayHintLength); - if (label.length > Server.config.maxInlayHintLength) { - newLabel += '…'; - } - return newLabel; - } - private async queryHints(documentUri: string): Promise { const request: InlayHintsParams = { textDocument: { uri: documentUri } diff --git a/editors/code/src/server.ts b/editors/code/src/server.ts index a3ef21a167..7907b70bc5 100644 --- a/editors/code/src/server.ts +++ b/editors/code/src/server.ts @@ -43,6 +43,7 @@ export class Server { initializationOptions: { publishDecorations: true, lruCapacity: Server.config.lruCapacity, + maxInlayHintLength: Server.config.maxInlayHintLength, excludeGlobs: Server.config.excludeGlobs, useClientWatching: Server.config.useClientWatching, featureFlags: Server.config.featureFlags From bf5ac4fe3952ee0db9fe18a185e39a209c58e79b Mon Sep 17 00:00:00 2001 From: Emil Lauridsen Date: Tue, 19 Nov 2019 17:40:38 +0100 Subject: [PATCH 02/24] Add test for inlay hint truncation --- crates/ra_ide_api/src/inlay_hints.rs | 37 ++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/crates/ra_ide_api/src/inlay_hints.rs b/crates/ra_ide_api/src/inlay_hints.rs index 6cd492b2a0..24a7ca5e71 100644 --- a/crates/ra_ide_api/src/inlay_hints.rs +++ b/crates/ra_ide_api/src/inlay_hints.rs @@ -514,4 +514,41 @@ fn main() { "### ); } + + #[test] + fn hint_truncation() { + let (analysis, file_id) = single_file( + r#" +struct Smol(T); + +struct VeryLongOuterName(T); + +fn main() { + let a = Smol(0u32); + let b = VeryLongOuterName(0usize); + let c = Smol(Smol(0u32)) +}"#, + ); + + assert_debug_snapshot!(analysis.inlay_hints(file_id, Some(8)).unwrap(), @r###" + [ + InlayHint { + range: [74; 75), + kind: TypeHint, + label: "Smol", + }, + InlayHint { + range: [98; 99), + kind: TypeHint, + label: "VeryLongOuterName<…>", + }, + InlayHint { + range: [137; 138), + kind: TypeHint, + label: "Smol>", + }, + ] + "### + ); + } } From e975f6364cb3caf50467835afb0dafce887f51f0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 00:02:44 +0300 Subject: [PATCH 03/24] add ws --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ee7afebcec..ea1c25d7f1 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frls-2.2E0 * API docs: https://rust-analyzer.github.io/rust-analyzer/ra_ide_api/ + ## License Rust analyzer is primarily distributed under the terms of both the MIT From 36e3fc9d5413f7e6e17e82867aae1318645880a3 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 09:40:36 +0300 Subject: [PATCH 04/24] Rename Source::ast -> Source::value --- .../src/assists/add_missing_impl_members.rs | 2 +- crates/ra_assists/src/assists/add_new.rs | 4 +- .../ra_assists/src/assists/fill_match_arms.rs | 2 +- crates/ra_cli/src/analysis_stats.rs | 4 +- crates/ra_hir/src/code_model.rs | 14 +++---- crates/ra_hir/src/code_model/attrs.rs | 6 +-- crates/ra_hir/src/code_model/docs.rs | 24 ++++++------ crates/ra_hir/src/code_model/src.rs | 24 ++++++------ crates/ra_hir/src/diagnostics.rs | 10 ++--- crates/ra_hir/src/expr.rs | 4 +- crates/ra_hir/src/from_source.rs | 38 +++++++++---------- crates/ra_hir/src/generics.rs | 16 ++++---- crates/ra_hir/src/lang_item.rs | 4 +- crates/ra_hir/src/source_binder.rs | 24 ++++++------ crates/ra_hir/src/traits.rs | 6 +-- crates/ra_hir/src/ty/tests.rs | 8 ++-- crates/ra_hir/src/type_alias.rs | 2 +- crates/ra_hir_def/src/adt.rs | 8 ++-- crates/ra_hir_def/src/body.rs | 12 +++--- crates/ra_hir_def/src/body/scope.rs | 9 +++-- crates/ra_hir_def/src/diagnostics.rs | 2 +- crates/ra_hir_def/src/imp.rs | 8 ++-- crates/ra_hir_def/src/lib.rs | 6 +-- crates/ra_hir_def/src/nameres/raw.rs | 2 +- crates/ra_hir_def/src/path.rs | 2 +- crates/ra_hir_expand/src/diagnostics.rs | 4 +- crates/ra_hir_expand/src/lib.rs | 34 +++++++++-------- .../src/completion/completion_context.rs | 2 +- .../ra_ide_api/src/completion/presentation.rs | 8 ++-- crates/ra_ide_api/src/diagnostics.rs | 2 +- .../src/display/function_signature.rs | 8 ++-- .../src/display/navigation_target.rs | 28 +++++++------- crates/ra_ide_api/src/expand.rs | 18 +++++---- crates/ra_ide_api/src/expand_macro.rs | 8 ++-- crates/ra_ide_api/src/goto_definition.rs | 8 ++-- crates/ra_ide_api/src/goto_type_definition.rs | 2 +- crates/ra_ide_api/src/hover.rs | 12 +++--- crates/ra_ide_api/src/impls.rs | 8 ++-- crates/ra_ide_api/src/parent_module.rs | 5 ++- crates/ra_ide_api/src/references/classify.rs | 8 ++-- .../src/references/name_definition.rs | 30 +++++++-------- crates/ra_ide_api/src/references/rename.rs | 4 +- .../ra_ide_api/src/references/search_scope.rs | 10 ++--- 43 files changed, 226 insertions(+), 214 deletions(-) diff --git a/crates/ra_assists/src/assists/add_missing_impl_members.rs b/crates/ra_assists/src/assists/add_missing_impl_members.rs index 91af161ee0..cef669cb5c 100644 --- a/crates/ra_assists/src/assists/add_missing_impl_members.rs +++ b/crates/ra_assists/src/assists/add_missing_impl_members.rs @@ -174,7 +174,7 @@ fn resolve_target_trait_def( .path()?; match analyzer.resolve_path(db, &ast_path) { - Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def.source(db).ast), + Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def.source(db).value), _ => None, } } diff --git a/crates/ra_assists/src/assists/add_new.rs b/crates/ra_assists/src/assists/add_new.rs index 2038afdc6f..b5f8afb4e7 100644 --- a/crates/ra_assists/src/assists/add_new.rs +++ b/crates/ra_assists/src/assists/add_new.rs @@ -141,7 +141,7 @@ fn find_struct_impl( })?; let struct_ty = { - let src = hir::Source { file_id: ctx.frange.file_id.into(), ast: strukt.clone() }; + let src = hir::Source { file_id: ctx.frange.file_id.into(), value: strukt.clone() }; hir::Struct::from_source(db, src).unwrap().ty(db) }; @@ -152,7 +152,7 @@ fn find_struct_impl( return false; } - let src = hir::Source { file_id: ctx.frange.file_id.into(), ast: impl_blk.clone() }; + let src = hir::Source { file_id: ctx.frange.file_id.into(), value: impl_blk.clone() }; let blk = hir::ImplBlock::from_source(db, src).unwrap(); let same_ty = blk.target_ty(db) == struct_ty; diff --git a/crates/ra_assists/src/assists/fill_match_arms.rs b/crates/ra_assists/src/assists/fill_match_arms.rs index b851c20823..9354466d96 100644 --- a/crates/ra_assists/src/assists/fill_match_arms.rs +++ b/crates/ra_assists/src/assists/fill_match_arms.rs @@ -84,7 +84,7 @@ fn resolve_enum_def( let expr_ty = analyzer.type_of(db, &expr)?; analyzer.autoderef(db, expr_ty).find_map(|ty| match ty.as_adt() { - Some((Adt::Enum(e), _)) => Some(e.source(db).ast), + Some((Adt::Enum(e), _)) => Some(e.source(db).value), _ => None, }) } diff --git a/crates/ra_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs index 3429a3c49f..9cd21e4b6e 100644 --- a/crates/ra_cli/src/analysis_stats.rs +++ b/crates/ra_cli/src/analysis_stats.rs @@ -98,7 +98,7 @@ pub fn run( let src = f.source(db); let original_file = src.file_id.original_file(db); let path = db.file_relative_path(original_file); - let syntax_range = src.ast.syntax().text_range(); + let syntax_range = src.value.syntax().text_range(); write!(msg, " ({:?} {})", path, syntax_range).unwrap(); } bar.set_message(&msg); @@ -135,7 +135,7 @@ pub fn run( let path = db.file_relative_path(original_file); let line_index = host.analysis().file_line_index(original_file).unwrap(); let text_range = src - .ast + .value .either(|it| it.syntax().text_range(), |it| it.syntax().text_range()); let (start, end) = ( line_index.line_col(text_range.start()), diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 731cc1fffb..cb990f4e23 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -139,7 +139,7 @@ impl Module { ) -> Either { let src = self.definition_source(db); let (_, source_map) = db.raw_items_with_source_map(src.file_id); - source_map.get(&src.ast, import) + source_map.get(&src.value, import) } /// Returns the crate this module is part of. @@ -206,7 +206,7 @@ impl Module { crate::ModuleDef::Function(f) => f.diagnostics(db, sink), crate::ModuleDef::Module(m) => { // Only add diagnostics from inline modules - if let ModuleSource::Module(_) = m.definition_source(db).ast { + if let ModuleSource::Module(_) = m.definition_source(db).value { m.diagnostics(db, sink) } } @@ -598,10 +598,10 @@ impl FnData { func: Function, ) -> Arc { let src = func.source(db); - let name = src.ast.name().map(|n| n.as_name()).unwrap_or_else(Name::missing); + let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing); let mut params = Vec::new(); let mut has_self_param = false; - if let Some(param_list) = src.ast.param_list() { + if let Some(param_list) = src.value.param_list() { if let Some(self_param) = param_list.self_param() { let self_type = if let Some(type_ref) = self_param.ascribed_type() { TypeRef::from_ast(type_ref) @@ -625,7 +625,7 @@ impl FnData { params.push(type_ref); } } - let ret_type = if let Some(type_ref) = src.ast.ret_type().and_then(|rt| rt.type_ref()) { + let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) { TypeRef::from_ast(type_ref) } else { TypeRef::unit() @@ -801,7 +801,7 @@ impl ConstData { db: &(impl DefDatabase + AstDatabase), konst: Const, ) -> Arc { - let node = konst.source(db).ast; + let node = konst.source(db).value; const_data_for(&node) } @@ -809,7 +809,7 @@ impl ConstData { db: &(impl DefDatabase + AstDatabase), konst: Static, ) -> Arc { - let node = konst.source(db).ast; + let node = konst.source(db).value; const_data_for(&node) } } diff --git a/crates/ra_hir/src/code_model/attrs.rs b/crates/ra_hir/src/code_model/attrs.rs index f7db36b668..9e304217c5 100644 --- a/crates/ra_hir/src/code_model/attrs.rs +++ b/crates/ra_hir/src/code_model/attrs.rs @@ -49,9 +49,9 @@ pub(crate) fn attributes_query( AttrDef::Module(it) => { let src = it.declaration_source(db)?; let hygiene = Hygiene::new(db, src.file_id); - Attr::from_attrs_owner(&src.ast, &hygiene) + Attr::from_attrs_owner(&src.value, &hygiene) } - AttrDef::StructField(it) => match it.source(db).ast { + AttrDef::StructField(it) => match it.source(db).value { FieldSource::Named(named) => { let src = it.source(db); let hygiene = Hygiene::new(db, src.file_id); @@ -82,7 +82,7 @@ where { let src = node.source(db); let hygiene = Hygiene::new(db, src.file_id); - Attr::from_attrs_owner(&src.ast, &hygiene) + Attr::from_attrs_owner(&src.value, &hygiene) } impl + Copy> Attrs for T { diff --git a/crates/ra_hir/src/code_model/docs.rs b/crates/ra_hir/src/code_model/docs.rs index 8533b4f5e6..e40efef34a 100644 --- a/crates/ra_hir/src/code_model/docs.rs +++ b/crates/ra_hir/src/code_model/docs.rs @@ -70,23 +70,23 @@ pub(crate) fn documentation_query( def: DocDef, ) -> Option { match def { - DocDef::Module(it) => docs_from_ast(&it.declaration_source(db)?.ast), - DocDef::StructField(it) => match it.source(db).ast { + DocDef::Module(it) => docs_from_ast(&it.declaration_source(db)?.value), + DocDef::StructField(it) => match it.source(db).value { FieldSource::Named(named) => docs_from_ast(&named), FieldSource::Pos(..) => None, }, DocDef::Adt(it) => match it { - Adt::Struct(it) => docs_from_ast(&it.source(db).ast), - Adt::Enum(it) => docs_from_ast(&it.source(db).ast), - Adt::Union(it) => docs_from_ast(&it.source(db).ast), + Adt::Struct(it) => docs_from_ast(&it.source(db).value), + Adt::Enum(it) => docs_from_ast(&it.source(db).value), + Adt::Union(it) => docs_from_ast(&it.source(db).value), }, - DocDef::EnumVariant(it) => docs_from_ast(&it.source(db).ast), - DocDef::Static(it) => docs_from_ast(&it.source(db).ast), - DocDef::Const(it) => docs_from_ast(&it.source(db).ast), - DocDef::Function(it) => docs_from_ast(&it.source(db).ast), - DocDef::Trait(it) => docs_from_ast(&it.source(db).ast), - DocDef::TypeAlias(it) => docs_from_ast(&it.source(db).ast), - DocDef::MacroDef(it) => docs_from_ast(&it.source(db).ast), + DocDef::EnumVariant(it) => docs_from_ast(&it.source(db).value), + DocDef::Static(it) => docs_from_ast(&it.source(db).value), + DocDef::Const(it) => docs_from_ast(&it.source(db).value), + DocDef::Function(it) => docs_from_ast(&it.source(db).value), + DocDef::Trait(it) => docs_from_ast(&it.source(db).value), + DocDef::TypeAlias(it) => docs_from_ast(&it.source(db).value), + DocDef::MacroDef(it) => docs_from_ast(&it.source(db).value), } } diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs index 247ae3e55d..556417b0f2 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/code_model/src.rs @@ -25,9 +25,9 @@ impl Module { let def_map = db.crate_def_map(self.id.krate); let decl_id = def_map[self.id.module_id].declaration; let file_id = def_map[self.id.module_id].definition; - let ast = ModuleSource::new(db, file_id, decl_id); + let value = ModuleSource::new(db, file_id, decl_id); let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id()); - Source { file_id, ast } + Source { file_id, value } } /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. @@ -38,8 +38,8 @@ impl Module { ) -> Option> { let def_map = db.crate_def_map(self.id.krate); let decl = def_map[self.id.module_id].declaration?; - let ast = decl.to_node(db); - Some(Source { file_id: decl.file_id(), ast }) + let value = decl.to_node(db); + Some(Source { file_id: decl.file_id(), value }) } } @@ -53,11 +53,11 @@ impl HasSource for StructField { let (file_id, struct_kind) = match self.parent { VariantDef::Struct(s) => { ss = s.source(db); - (ss.file_id, ss.ast.kind()) + (ss.file_id, ss.value.kind()) } VariantDef::EnumVariant(e) => { es = e.source(db); - (es.file_id, es.ast.kind()) + (es.file_id, es.value.kind()) } }; @@ -66,13 +66,13 @@ impl HasSource for StructField { ast::StructKind::Named(fl) => fl.fields().map(|it| FieldSource::Named(it)).collect(), ast::StructKind::Unit => Vec::new(), }; - let ast = field_sources + let value = field_sources .into_iter() .zip(fields.iter()) .find(|(_syntax, (id, _))| *id == self.id) .unwrap() .0; - Source { file_id, ast } + Source { file_id, value } } } impl HasSource for Struct { @@ -98,8 +98,8 @@ impl HasSource for EnumVariant { fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source { let enum_data = db.enum_data(self.parent.id); let src = self.parent.id.source(db); - let ast = src - .ast + let value = src + .value .variant_list() .into_iter() .flat_map(|it| it.variants()) @@ -107,7 +107,7 @@ impl HasSource for EnumVariant { .find(|(_syntax, (id, _))| *id == self.id) .unwrap() .0; - Source { file_id: src.file_id, ast } + Source { file_id: src.file_id, value } } } impl HasSource for Function { @@ -143,7 +143,7 @@ impl HasSource for TypeAlias { impl HasSource for MacroDef { type Ast = ast::MacroCall; fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source { - Source { file_id: self.id.ast_id.file_id(), ast: self.id.ast_id.to_node(db) } + Source { file_id: self.id.ast_id.file_id(), value: self.id.ast_id.to_node(db) } } } diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs index 1751e7be33..7d1b648589 100644 --- a/crates/ra_hir/src/diagnostics.rs +++ b/crates/ra_hir/src/diagnostics.rs @@ -21,7 +21,7 @@ impl Diagnostic for NoSuchField { } fn source(&self) -> Source { - Source { file_id: self.file, ast: self.field.into() } + Source { file_id: self.file, value: self.field.into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -41,7 +41,7 @@ impl Diagnostic for MissingFields { "fill structure fields".to_string() } fn source(&self) -> Source { - Source { file_id: self.file, ast: self.field_list.into() } + Source { file_id: self.file, value: self.field_list.into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { self @@ -53,7 +53,7 @@ impl AstDiagnostic for MissingFields { fn ast(&self, db: &impl AstDatabase) -> Self::AST { let root = db.parse_or_expand(self.source().file_id).unwrap(); - let node = self.source().ast.to_node(&root); + let node = self.source().value.to_node(&root); ast::RecordFieldList::cast(node).unwrap() } } @@ -69,7 +69,7 @@ impl Diagnostic for MissingOkInTailExpr { "wrap return expression in Ok".to_string() } fn source(&self) -> Source { - Source { file_id: self.file, ast: self.expr.into() } + Source { file_id: self.file, value: self.expr.into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { self @@ -81,7 +81,7 @@ impl AstDiagnostic for MissingOkInTailExpr { fn ast(&self, db: &impl AstDatabase) -> Self::AST { let root = db.parse_or_expand(self.file).unwrap(); - let node = self.source().ast.to_node(&root); + let node = self.source().value.to_node(&root); ast::Expr::cast(node).unwrap() } } diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index e3733779e9..8bfdda45e1 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -116,7 +116,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> { let source_map = self.func.body_source_map(db); if let Some(source_ptr) = source_map.expr_syntax(id) { - if let Some(expr) = source_ptr.ast.a() { + if let Some(expr) = source_ptr.value.a() { let root = source_ptr.file_syntax(db); if let ast::Expr::RecordLit(record_lit) = expr.to_node(&root) { if let Some(field_list) = record_lit.record_field_list() { @@ -161,7 +161,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> { let source_map = self.func.body_source_map(db); if let Some(source_ptr) = source_map.expr_syntax(id) { - if let Some(expr) = source_ptr.ast.a() { + if let Some(expr) = source_ptr.value.a() { self.sink.push(MissingOkInTailExpr { file: source_ptr.file_id, expr }); } } diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 1c26756c97..f4dca25cb6 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -87,7 +87,7 @@ impl FromSource for MacroDef { let module = Module::from_definition(db, Source::new(src.file_id, module_src))?; let krate = module.krate().crate_id(); - let ast_id = AstId::new(src.file_id, db.ast_id_map(src.file_id).ast_id(&src.ast)); + let ast_id = AstId::new(src.file_id, db.ast_id_map(src.file_id).ast_id(&src.value)); let id: MacroDefId = MacroDefId { krate, ast_id, kind }; Some(MacroDef { id }) @@ -105,8 +105,8 @@ impl FromSource for ImplBlock { impl FromSource for EnumVariant { type Ast = ast::EnumVariant; fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { - let parent_enum = src.ast.parent_enum(); - let src_enum = Source { file_id: src.file_id, ast: parent_enum }; + let parent_enum = src.value.parent_enum(); + let src_enum = Source { file_id: src.file_id, value: parent_enum }; let variants = Enum::from_source(db, src_enum)?.variants(db); variants.into_iter().find(|v| v.source(db) == src) } @@ -115,16 +115,16 @@ impl FromSource for EnumVariant { impl FromSource for StructField { type Ast = FieldSource; fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { - let variant_def: VariantDef = match src.ast { + let variant_def: VariantDef = match src.value { FieldSource::Named(ref field) => { - let ast = field.syntax().ancestors().find_map(ast::StructDef::cast)?; - let src = Source { file_id: src.file_id, ast }; + let value = field.syntax().ancestors().find_map(ast::StructDef::cast)?; + let src = Source { file_id: src.file_id, value }; let def = Struct::from_source(db, src)?; VariantDef::from(def) } FieldSource::Pos(ref field) => { - let ast = field.syntax().ancestors().find_map(ast::EnumVariant::cast)?; - let src = Source { file_id: src.file_id, ast }; + let value = field.syntax().ancestors().find_map(ast::EnumVariant::cast)?; + let src = Source { file_id: src.file_id, value }; let def = EnumVariant::from_source(db, src)?; VariantDef::from(def) } @@ -142,12 +142,12 @@ impl FromSource for StructField { impl Local { pub fn from_source(db: &impl HirDatabase, src: Source) -> Option { let file_id = src.file_id; - let parent: DefWithBody = src.ast.syntax().ancestors().find_map(|it| { + let parent: DefWithBody = src.value.syntax().ancestors().find_map(|it| { let res = match_ast! { match it { - ast::ConstDef(ast) => { Const::from_source(db, Source { ast, file_id})?.into() }, - ast::StaticDef(ast) => { Static::from_source(db, Source { ast, file_id})?.into() }, - ast::FnDef(ast) => { Function::from_source(db, Source { ast, file_id})?.into() }, + ast::ConstDef(value) => { Const::from_source(db, Source { value, file_id})?.into() }, + ast::StaticDef(value) => { Static::from_source(db, Source { value, file_id})?.into() }, + ast::FnDef(value) => { Function::from_source(db, Source { value, file_id})?.into() }, _ => return None, } }; @@ -162,33 +162,33 @@ impl Local { impl Module { pub fn from_declaration(db: &impl DefDatabase, src: Source) -> Option { - let parent_declaration = src.ast.syntax().ancestors().skip(1).find_map(ast::Module::cast); + let parent_declaration = src.value.syntax().ancestors().skip(1).find_map(ast::Module::cast); let parent_module = match parent_declaration { Some(parent_declaration) => { - let src_parent = Source { file_id: src.file_id, ast: parent_declaration }; + let src_parent = Source { file_id: src.file_id, value: parent_declaration }; Module::from_declaration(db, src_parent) } _ => { let src_parent = Source { file_id: src.file_id, - ast: ModuleSource::new(db, Some(src.file_id.original_file(db)), None), + value: ModuleSource::new(db, Some(src.file_id.original_file(db)), None), }; Module::from_definition(db, src_parent) } }?; - let child_name = src.ast.name()?; + let child_name = src.value.name()?; parent_module.child(db, &child_name.as_name()) } pub fn from_definition(db: &impl DefDatabase, src: Source) -> Option { - match src.ast { + match src.value { ModuleSource::Module(ref module) => { assert!(!module.has_semi()); return Module::from_declaration( db, - Source { file_id: src.file_id, ast: module.clone() }, + Source { file_id: src.file_id, value: module.clone() }, ); } ModuleSource::SourceFile(_) => (), @@ -214,5 +214,5 @@ where let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); let module = Module::from_definition(db, Source::new(src.file_id, module_src))?; let ctx = LocationCtx::new(db, module.id, src.file_id); - Some(DEF::from_ast(ctx, &src.ast)) + Some(DEF::from_ast(ctx, &src.value)) } diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index c35482ae8e..8925ba3a9f 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs @@ -91,10 +91,10 @@ impl GenericParams { let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; // FIXME: add `: Sized` bound for everything except for `Self` in traits match def { - GenericDef::Function(it) => generics.fill(&it.source(db).ast, start), - GenericDef::Adt(Adt::Struct(it)) => generics.fill(&it.source(db).ast, start), - GenericDef::Adt(Adt::Union(it)) => generics.fill(&it.source(db).ast, start), - GenericDef::Adt(Adt::Enum(it)) => generics.fill(&it.source(db).ast, start), + GenericDef::Function(it) => generics.fill(&it.source(db).value, start), + GenericDef::Adt(Adt::Struct(it)) => generics.fill(&it.source(db).value, start), + GenericDef::Adt(Adt::Union(it)) => generics.fill(&it.source(db).value, start), + GenericDef::Adt(Adt::Enum(it)) => generics.fill(&it.source(db).value, start), GenericDef::Trait(it) => { // traits get the Self type as an implicit first type parameter generics.params.push(GenericParam { @@ -102,17 +102,17 @@ impl GenericParams { name: name::SELF_TYPE, default: None, }); - generics.fill(&it.source(db).ast, start + 1); + generics.fill(&it.source(db).value, start + 1); // add super traits as bounds on Self // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar let self_param = TypeRef::Path(name::SELF_TYPE.into()); - generics.fill_bounds(&it.source(db).ast, self_param); + generics.fill_bounds(&it.source(db).value, self_param); } - GenericDef::TypeAlias(it) => generics.fill(&it.source(db).ast, start), + GenericDef::TypeAlias(it) => generics.fill(&it.source(db).value, start), // Note that we don't add `Self` here: in `impl`s, `Self` is not a // type-parameter, but rather is a type-alias for impl's target // type, so this is handled by the resolver. - GenericDef::ImplBlock(it) => generics.fill(&it.source(db).ast, start), + GenericDef::ImplBlock(it) => generics.fill(&it.source(db).value, start), GenericDef::EnumVariant(_) | GenericDef::Const(_) => {} } diff --git a/crates/ra_hir/src/lang_item.rs b/crates/ra_hir/src/lang_item.rs index fa2ef8a173..89fd85f59f 100644 --- a/crates/ra_hir/src/lang_item.rs +++ b/crates/ra_hir/src/lang_item.rs @@ -97,7 +97,7 @@ impl LangItems { // Look for impl targets for impl_block in module.impl_blocks(db) { let src = impl_block.source(db); - if let Some(lang_item_name) = lang_item_name(&src.ast) { + if let Some(lang_item_name) = lang_item_name(&src.value) { self.items .entry(lang_item_name) .or_insert_with(|| LangItemTarget::ImplBlock(impl_block)); @@ -144,7 +144,7 @@ impl LangItems { T: Copy + HasSource, N: AttrsOwner, { - let node = item.source(db).ast; + let node = item.source(db).value; if let Some(lang_item_name) = lang_item_name(&node) { self.items.entry(lang_item_name).or_insert_with(|| constructor(item)); } diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 5d3196c2a2..471b0b0891 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -31,7 +31,7 @@ use crate::{ fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option { match_ast! { - match (node.ast) { + match (node.value) { ast::Module(it) => { let src = node.with_ast(it); Some(crate::Module::from_declaration(db, src)?.resolver(db)) @@ -48,7 +48,7 @@ fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) - let src = node.with_ast(it); Some(Enum::from_source(db, src)?.resolver(db)) }, - _ => match node.ast.kind() { + _ => match node.value.kind() { FN_DEF | CONST_DEF | STATIC_DEF => { Some(def_with_body_from_child_node(db, node)?.resolver(db)) } @@ -67,7 +67,7 @@ fn def_with_body_from_child_node( let module = Module::from_definition(db, Source::new(child.file_id, module_source))?; let ctx = LocationCtx::new(db, module.id, child.file_id); - child.ast.ancestors().find_map(|node| { + child.value.ancestors().find_map(|node| { match_ast! { match node { ast::FnDef(def) => { Some(Function {id: ctx.to_def(&def) }.into()) }, @@ -171,7 +171,7 @@ impl SourceAnalyzer { } else { SourceAnalyzer { resolver: node - .ast + .value .ancestors() .find_map(|it| try_get_resolver_for_node(db, node.with_ast(&it))) .unwrap_or_default(), @@ -185,12 +185,12 @@ impl SourceAnalyzer { } fn expr_id(&self, expr: &ast::Expr) -> Option { - let src = Source { file_id: self.file_id, ast: expr }; + let src = Source { file_id: self.file_id, value: expr }; self.body_source_map.as_ref()?.node_expr(src) } fn pat_id(&self, pat: &ast::Pat) -> Option { - let src = Source { file_id: self.file_id, ast: pat }; + let src = Source { file_id: self.file_id, value: pat }; self.body_source_map.as_ref()?.node_pat(src) } @@ -302,7 +302,7 @@ impl SourceAnalyzer { let entry = scopes.resolve_name_in_scope(scope, &name)?; Some(ScopeEntryWithSyntax { name: entry.name().clone(), - ptr: source_map.pat_syntax(entry.pat())?.ast, + ptr: source_map.pat_syntax(entry.pat())?.value, }) } @@ -428,7 +428,7 @@ fn scope_for( source_map: &BodySourceMap, node: Source<&SyntaxNode>, ) -> Option { - node.ast + node.value .ancestors() .filter_map(ast::Expr::cast) .filter_map(|it| source_map.node_expr(Source::new(node.file_id, &it))) @@ -450,18 +450,18 @@ fn scope_for_offset( return None; } let syntax_node_ptr = - source.ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); + source.value.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); Some((syntax_node_ptr, scope)) }) // find containing scope .min_by_key(|(ptr, _scope)| { ( - !(ptr.range().start() <= offset.ast && offset.ast <= ptr.range().end()), + !(ptr.range().start() <= offset.value && offset.value <= ptr.range().end()), ptr.range().len(), ) }) .map(|(ptr, scope)| { - adjust(scopes, source_map, ptr, offset.file_id, offset.ast).unwrap_or(*scope) + adjust(scopes, source_map, ptr, offset.file_id, offset.value).unwrap_or(*scope) }) } @@ -485,7 +485,7 @@ fn adjust( return None; } let syntax_node_ptr = - source.ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); + source.value.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); Some((syntax_node_ptr, scope)) }) .map(|(ptr, scope)| (ptr.range(), scope)) diff --git a/crates/ra_hir/src/traits.rs b/crates/ra_hir/src/traits.rs index 1a45dacba9..858972c6fe 100644 --- a/crates/ra_hir/src/traits.rs +++ b/crates/ra_hir/src/traits.rs @@ -26,11 +26,11 @@ impl TraitData { tr: Trait, ) -> Arc { let src = tr.source(db); - let name = src.ast.name().map(|n| n.as_name()); + let name = src.value.name().map(|n| n.as_name()); let module = tr.module(db); let ctx = LocationCtx::new(db, module.id, src.file_id); - let auto = src.ast.is_auto(); - let items = if let Some(item_list) = src.ast.item_list() { + let auto = src.value.is_auto(); + let items = if let Some(item_list) = src.value.item_list() { item_list .impl_items() .map(|item_node| match item_node { diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index ca16936796..c1024d03c7 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -4694,14 +4694,16 @@ fn infer(content: &str) -> String { } // sort ranges for consistency - types.sort_by_key(|(src_ptr, _)| (src_ptr.ast.range().start(), src_ptr.ast.range().end())); + types.sort_by_key(|(src_ptr, _)| { + (src_ptr.value.range().start(), src_ptr.value.range().end()) + }); for (src_ptr, ty) in &types { - let node = src_ptr.ast.to_node(&src_ptr.file_syntax(&db)); + let node = src_ptr.value.to_node(&src_ptr.file_syntax(&db)); let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) { (self_param.self_kw_token().text_range(), "self".to_string()) } else { - (src_ptr.ast.range(), node.text().to_string().replace("\n", " ")) + (src_ptr.value.range(), node.text().to_string().replace("\n", " ")) }; let macro_prefix = if src_ptr.file_id != file_id.into() { "!" } else { "" }; write!( diff --git a/crates/ra_hir/src/type_alias.rs b/crates/ra_hir/src/type_alias.rs index 078e6295ea..392f244cf1 100644 --- a/crates/ra_hir/src/type_alias.rs +++ b/crates/ra_hir/src/type_alias.rs @@ -23,7 +23,7 @@ impl TypeAliasData { db: &(impl DefDatabase + AstDatabase), typ: TypeAlias, ) -> Arc { - let node = typ.source(db).ast; + let node = typ.source(db).value; let name = node.name().map_or_else(Name::missing, |n| n.as_name()); let type_ref = node.type_ref().map(TypeRef::from_ast); Arc::new(TypeAliasData { name, type_ref }) diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index a29c4d41e5..d04f54e15a 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs @@ -54,8 +54,8 @@ impl StructData { id: StructOrUnionId, ) -> Arc { let src = id.source(db); - let name = src.ast.name().map(|n| n.as_name()); - let variant_data = VariantData::new(src.ast.kind()); + let name = src.value.name().map(|n| n.as_name()); + let variant_data = VariantData::new(src.value.kind()); let variant_data = Arc::new(variant_data); Arc::new(StructData { name, variant_data }) } @@ -64,9 +64,9 @@ impl StructData { impl EnumData { pub(crate) fn enum_data_query(db: &impl DefDatabase2, e: EnumId) -> Arc { let src = e.source(db); - let name = src.ast.name().map(|n| n.as_name()); + let name = src.value.name().map(|n| n.as_name()); let variants = src - .ast + .value .variant_list() .into_iter() .flat_map(|it| it.variants()) diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 85dc4feb0a..3804b65c7e 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -73,8 +73,8 @@ impl Expander { std::mem::forget(mark); } - fn to_source(&self, ast: T) -> Source { - Source { file_id: self.current_file_id, ast } + fn to_source(&self, value: T) -> Source { + Source { file_id: self.current_file_id, value } } fn parse_path(&mut self, path: ast::Path) -> Option { @@ -150,16 +150,16 @@ impl Body { let (file_id, module, body) = match def { DefWithBodyId::FunctionId(f) => { let src = f.source(db); - params = src.ast.param_list(); - (src.file_id, f.module(db), src.ast.body().map(ast::Expr::from)) + params = src.value.param_list(); + (src.file_id, f.module(db), src.value.body().map(ast::Expr::from)) } DefWithBodyId::ConstId(c) => { let src = c.source(db); - (src.file_id, c.module(db), src.ast.body()) + (src.file_id, c.module(db), src.value.body()) } DefWithBodyId::StaticId(s) => { let src = s.source(db); - (src.file_id, s.module(db), src.ast.body()) + (src.file_id, s.module(db), src.value.body()) } }; let expander = Expander::new(db, file_id, module); diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs index 10cb87d37b..aeb71ff229 100644 --- a/crates/ra_hir_def/src/body/scope.rs +++ b/crates/ra_hir_def/src/body/scope.rs @@ -210,8 +210,9 @@ mod tests { let scopes = db.expr_scopes(function.into()); let (_body, source_map) = db.body_with_source_map(function.into()); - let expr_id = - source_map.node_expr(Source { file_id: file_id.into(), ast: &marker.into() }).unwrap(); + let expr_id = source_map + .node_expr(Source { file_id: file_id.into(), value: &marker.into() }) + .unwrap(); let scope = scopes.scope_for(expr_id); let actual = scopes @@ -317,14 +318,14 @@ mod tests { let expr_scope = { let expr_ast = name_ref.syntax().ancestors().find_map(ast::Expr::cast).unwrap(); let expr_id = - source_map.node_expr(Source { file_id: file_id.into(), ast: &expr_ast }).unwrap(); + source_map.node_expr(Source { file_id: file_id.into(), value: &expr_ast }).unwrap(); scopes.scope_for(expr_id).unwrap() }; let resolved = scopes.resolve_name_in_scope(expr_scope, &name_ref.as_name()).unwrap(); let pat_src = source_map.pat_syntax(resolved.pat()).unwrap(); - let local_name = pat_src.ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); + let local_name = pat_src.value.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); assert_eq!(local_name.range(), expected_name.syntax().text_range()); } diff --git a/crates/ra_hir_def/src/diagnostics.rs b/crates/ra_hir_def/src/diagnostics.rs index 9843009a5d..eda9b2269a 100644 --- a/crates/ra_hir_def/src/diagnostics.rs +++ b/crates/ra_hir_def/src/diagnostics.rs @@ -20,7 +20,7 @@ impl Diagnostic for UnresolvedModule { "unresolved module".to_string() } fn source(&self) -> Source { - Source { file_id: self.file, ast: self.decl.into() } + Source { file_id: self.file, value: self.decl.into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { self diff --git a/crates/ra_hir_def/src/imp.rs b/crates/ra_hir_def/src/imp.rs index 717991c405..4323dfcb69 100644 --- a/crates/ra_hir_def/src/imp.rs +++ b/crates/ra_hir_def/src/imp.rs @@ -25,11 +25,11 @@ impl ImplData { let src = id.source(db); let items = db.ast_id_map(src.file_id); - let target_trait = src.ast.target_trait().map(TypeRef::from_ast); - let target_type = TypeRef::from_ast_opt(src.ast.target_type()); - let negative = src.ast.is_negative(); + let target_trait = src.value.target_trait().map(TypeRef::from_ast); + let target_type = TypeRef::from_ast_opt(src.value.target_type()); + let negative = src.value.is_negative(); - let items = if let Some(item_list) = src.ast.item_list() { + let items = if let Some(item_list) = src.value.item_list() { let ctx = LocationCtx::new(db, id.module(db), src.file_id); item_list .impl_items() diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index a240a10b82..50caf4f836 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -80,7 +80,7 @@ impl ModuleSource { pub fn from_child_node(db: &impl db::DefDatabase2, child: Source<&SyntaxNode>) -> ModuleSource { if let Some(m) = - child.ast.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) + child.value.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) { ModuleSource::Module(m) } else { @@ -184,8 +184,8 @@ pub trait AstItemDef: salsa::InternKey + Clone { } fn source(self, db: &(impl AstDatabase + InternDatabase)) -> Source { let loc = self.lookup_intern(db); - let ast = loc.ast_id.to_node(db); - Source { file_id: loc.ast_id.file_id(), ast } + let value = loc.ast_id.to_node(db); + Source { file_id: loc.ast_id.file_id(), value } } fn module(self, db: &impl InternDatabase) -> ModuleId { let loc = self.lookup_intern(db); diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index a0a2c7273c..7c68fd6380 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs @@ -327,7 +327,7 @@ impl RawItemsCollector { let mut buf = Vec::new(); Path::expand_use_item( - Source { ast: use_item, file_id: self.file_id }, + Source { value: use_item, file_id: self.file_id }, &self.hygiene, |path, use_tree, is_glob, alias| { let import_data = ImportData { diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 04039376f3..626ebffdc8 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -71,7 +71,7 @@ impl Path { hygiene: &Hygiene, mut cb: impl FnMut(Path, &ast::UseTree, bool, Option), ) { - if let Some(tree) = item_src.ast.use_tree() { + if let Some(tree) = item_src.value.use_tree() { expand_use_tree(None, tree, hygiene, &mut cb); } } diff --git a/crates/ra_hir_expand/src/diagnostics.rs b/crates/ra_hir_expand/src/diagnostics.rs index 201884b957..3d37e93358 100644 --- a/crates/ra_hir_expand/src/diagnostics.rs +++ b/crates/ra_hir_expand/src/diagnostics.rs @@ -24,7 +24,7 @@ pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static { fn message(&self) -> String; fn source(&self) -> Source; fn highlight_range(&self) -> TextRange { - self.source().ast.range() + self.source().value.range() } fn as_any(&self) -> &(dyn Any + Send + 'static); } @@ -37,7 +37,7 @@ pub trait AstDiagnostic { impl dyn Diagnostic { pub fn syntax_node(&self, db: &impl AstDatabase) -> SyntaxNode { let node = db.parse_or_expand(self.source().file_id).unwrap(); - self.source().ast.to_node(&node) + self.source().value.to_node(&node) } pub fn downcast_ref(&self) -> Option<&D> { diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index cfe7e6d159..6ca4bc7a39 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs @@ -166,19 +166,19 @@ impl ExpansionInfo { pub fn map_token_down(&self, token: Source<&SyntaxToken>) -> Option> { assert_eq!(token.file_id, self.arg.file_id); let range = - token.ast.text_range().checked_sub(self.arg.ast.syntax().text_range().start())?; + token.value.text_range().checked_sub(self.arg.value.syntax().text_range().start())?; let token_id = self.macro_arg.1.token_by_range(range)?; let token_id = self.macro_def.0.map_id_down(token_id); let range = self.exp_map.range_by_token(token_id)?; - let token = algo::find_covering_element(&self.expanded.ast, range).into_token()?; + let token = algo::find_covering_element(&self.expanded.value, range).into_token()?; Some(self.expanded.with_ast(token)) } pub fn map_token_up(&self, token: Source<&SyntaxToken>) -> Option> { - let token_id = self.exp_map.token_by_range(token.ast.text_range())?; + let token_id = self.exp_map.token_by_range(token.value.text_range())?; let (token_id, origin) = self.macro_def.0.map_id_up(token_id); let (token_map, tt) = match origin { @@ -188,8 +188,8 @@ impl ExpansionInfo { let range = token_map.range_by_token(token_id)?; let token = algo::find_covering_element( - tt.ast.syntax(), - range + tt.ast.syntax().text_range().start(), + tt.value.syntax(), + range + tt.value.syntax().text_range().start(), ) .into_token()?; Some(tt.with_ast(token)) @@ -240,30 +240,34 @@ impl AstId { } } -/// FIXME: https://github.com/matklad/with ? +/// `Source` stores a value of `T` inside a particular file/syntax tree. +/// +/// Typical usages are: +/// +/// * `Source` -- syntax node in a file +/// * `Source` -- ast node in a file +/// * `Source` -- offset in a file #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct Source { pub file_id: HirFileId, - // FIXME: this stores all kind of things, not only `ast`. - // There should be a better name... - pub ast: T, + pub value: T, } impl Source { - pub fn new(file_id: HirFileId, ast: T) -> Source { - Source { file_id, ast } + pub fn new(file_id: HirFileId, value: T) -> Source { + Source { file_id, value } } // Similarly, naming here is stupid... - pub fn with_ast(&self, ast: U) -> Source { - Source::new(self.file_id, ast) + pub fn with_ast(&self, value: U) -> Source { + Source::new(self.file_id, value) } pub fn map U, U>(self, f: F) -> Source { - Source::new(self.file_id, f(self.ast)) + Source::new(self.file_id, f(self.value)) } pub fn as_ref(&self) -> Source<&T> { - self.with_ast(&self.ast) + self.with_ast(&self.value) } pub fn file_syntax(&self, db: &impl db::AstDatabase) -> SyntaxNode { db.parse_or_expand(self.file_id).expect("source created from invalid file") diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs index 0906a4e1b6..b8345c91d5 100644 --- a/crates/ra_ide_api/src/completion/completion_context.rs +++ b/crates/ra_ide_api/src/completion/completion_context.rs @@ -54,7 +54,7 @@ impl<'a> CompletionContext<'a> { let src = hir::ModuleSource::from_position(db, position); let module = hir::Module::from_definition( db, - hir::Source { file_id: position.file_id.into(), ast: src }, + hir::Source { file_id: position.file_id.into(), value: src }, ); let token = original_parse.tree().syntax().token_at_offset(position.offset).left_biased()?; diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs index 501b7da4e7..b20329459c 100644 --- a/crates/ra_ide_api/src/completion/presentation.rs +++ b/crates/ra_ide_api/src/completion/presentation.rs @@ -169,7 +169,7 @@ impl Completions { None => return, }; - let ast_node = macro_.source(ctx.db).ast; + let ast_node = macro_.source(ctx.db).value; let detail = macro_label(&ast_node); let docs = macro_.docs(ctx.db); @@ -201,7 +201,7 @@ impl Completions { ) { let data = func.data(ctx.db); let name = name.unwrap_or_else(|| data.name().to_string()); - let ast_node = func.source(ctx.db).ast; + let ast_node = func.source(ctx.db).value; let detail = function_label(&ast_node); let mut builder = @@ -234,7 +234,7 @@ impl Completions { } pub(crate) fn add_const(&mut self, ctx: &CompletionContext, constant: hir::Const) { - let ast_node = constant.source(ctx.db).ast; + let ast_node = constant.source(ctx.db).value; let name = match ast_node.name() { Some(name) => name, _ => return, @@ -250,7 +250,7 @@ impl Completions { } pub(crate) fn add_type_alias(&mut self, ctx: &CompletionContext, type_alias: hir::TypeAlias) { - let type_def = type_alias.source(ctx.db).ast; + let type_def = type_alias.source(ctx.db).value; let name = match type_def.name() { Some(name) => name, _ => return, diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs index e52ffefb36..cc1ccab4b5 100644 --- a/crates/ra_ide_api/src/diagnostics.rs +++ b/crates/ra_ide_api/src/diagnostics.rs @@ -96,7 +96,7 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec }); let source_file = db.parse(file_id).tree(); let src = - hir::Source { file_id: file_id.into(), ast: hir::ModuleSource::SourceFile(source_file) }; + hir::Source { file_id: file_id.into(), value: hir::ModuleSource::SourceFile(source_file) }; if let Some(m) = hir::Module::from_definition(db, src) { m.diagnostics(db, &mut sink); }; diff --git a/crates/ra_ide_api/src/display/function_signature.rs b/crates/ra_ide_api/src/display/function_signature.rs index 9075ca443c..f42dffc876 100644 --- a/crates/ra_ide_api/src/display/function_signature.rs +++ b/crates/ra_ide_api/src/display/function_signature.rs @@ -48,12 +48,12 @@ impl FunctionSignature { pub(crate) fn from_hir(db: &db::RootDatabase, function: hir::Function) -> Self { let doc = function.docs(db); - let ast_node = function.source(db).ast; + let ast_node = function.source(db).value; FunctionSignature::from(&ast_node).with_doc_opt(doc) } pub(crate) fn from_struct(db: &db::RootDatabase, st: hir::Struct) -> Option { - let node: ast::StructDef = st.source(db).ast; + let node: ast::StructDef = st.source(db).value; match node.kind() { ast::StructKind::Named(_) => return None, _ => (), @@ -87,7 +87,7 @@ impl FunctionSignature { db: &db::RootDatabase, variant: hir::EnumVariant, ) -> Option { - let node: ast::EnumVariant = variant.source(db).ast; + let node: ast::EnumVariant = variant.source(db).value; match node.kind() { ast::StructKind::Named(_) | ast::StructKind::Unit => return None, _ => (), @@ -126,7 +126,7 @@ impl FunctionSignature { } pub(crate) fn from_macro(db: &db::RootDatabase, macro_def: hir::MacroDef) -> Option { - let node: ast::MacroCall = macro_def.source(db).ast; + let node: ast::MacroCall = macro_def.source(db).value; let params = vec![]; diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs index b30ef8e054..50accafd03 100644 --- a/crates/ra_ide_api/src/display/navigation_target.rs +++ b/crates/ra_ide_api/src/display/navigation_target.rs @@ -86,9 +86,9 @@ impl NavigationTarget { name, None, frange.range, - src.ast.syntax().kind(), - src.ast.doc_comment_text(), - src.ast.short_label(), + src.value.syntax().kind(), + src.value.doc_comment_text(), + src.value.short_label(), ); } module.to_nav(db) @@ -146,9 +146,9 @@ impl NavigationTarget { description: Option, ) -> NavigationTarget { //FIXME: use `_` instead of empty string - let name = node.ast.name().map(|it| it.text().clone()).unwrap_or_default(); + let name = node.value.name().map(|it| it.text().clone()).unwrap_or_default(); let focus_range = - node.ast.name().map(|it| original_range(db, node.with_ast(it.syntax())).range); + node.value.name().map(|it| original_range(db, node.with_ast(it.syntax())).range); let frange = original_range(db, node.map(|it| it.syntax())); NavigationTarget::from_syntax( @@ -156,7 +156,7 @@ impl NavigationTarget { name, focus_range, frange.range, - node.ast.syntax().kind(), + node.value.syntax().kind(), docs, description, ) @@ -220,8 +220,8 @@ where NavigationTarget::from_named( db, src.as_ref().map(|it| it as &dyn ast::NameOwner), - src.ast.doc_comment_text(), - src.ast.short_label(), + src.value.doc_comment_text(), + src.value.short_label(), ) } } @@ -230,7 +230,7 @@ impl ToNav for hir::Module { fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { let src = self.definition_source(db); let name = self.name(db).map(|it| it.to_string().into()).unwrap_or_default(); - match &src.ast { + match &src.value { ModuleSource::SourceFile(node) => { let frange = original_range(db, src.with_ast(node.syntax())); @@ -271,7 +271,7 @@ impl ToNav for hir::ImplBlock { "impl".into(), None, frange.range, - src.ast.syntax().kind(), + src.value.syntax().kind(), None, None, ) @@ -282,7 +282,7 @@ impl ToNav for hir::StructField { fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { let src = self.source(db); - match &src.ast { + match &src.value { FieldSource::Named(it) => NavigationTarget::from_named( db, src.with_ast(it), @@ -308,11 +308,11 @@ impl ToNav for hir::StructField { impl ToNav for hir::MacroDef { fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { let src = self.source(db); - log::debug!("nav target {:#?}", src.ast.syntax()); + log::debug!("nav target {:#?}", src.value.syntax()); NavigationTarget::from_named( db, src.as_ref().map(|it| it as &dyn ast::NameOwner), - src.ast.doc_comment_text(), + src.value.doc_comment_text(), None, ) } @@ -341,7 +341,7 @@ impl ToNav for hir::AssocItem { impl ToNav for hir::Local { fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { let src = self.source(db); - let (full_range, focus_range) = match src.ast { + let (full_range, focus_range) = match src.value { Either::A(it) => { (it.syntax().text_range(), it.name().map(|it| it.syntax().text_range())) } diff --git a/crates/ra_ide_api/src/expand.rs b/crates/ra_ide_api/src/expand.rs index 7f59e46d26..0228bced90 100644 --- a/crates/ra_ide_api/src/expand.rs +++ b/crates/ra_ide_api/src/expand.rs @@ -12,7 +12,7 @@ pub(crate) fn original_range(db: &RootDatabase, node: Source<&SyntaxNode>) -> Fi None => { return FileRange { file_id: node.file_id.original_file(db), - range: node.ast.text_range(), + range: node.value.text_range(), } } Some(it) => it, @@ -25,14 +25,18 @@ pub(crate) fn original_range(db: &RootDatabase, node: Source<&SyntaxNode>) -> Fi // *Second*, we should handle recurside macro expansions let token = node - .ast + .value .descendants_with_tokens() .filter_map(|it| it.into_token()) .find_map(|it| expansion.map_token_up(node.with_ast(&it))); match token { - Some(it) => FileRange { file_id: it.file_id.original_file(db), range: it.ast.text_range() }, - None => FileRange { file_id: node.file_id.original_file(db), range: node.ast.text_range() }, + Some(it) => { + FileRange { file_id: it.file_id.original_file(db), range: it.value.text_range() } + } + None => { + FileRange { file_id: node.file_id.original_file(db), range: node.value.text_range() } + } } } @@ -44,13 +48,13 @@ pub(crate) fn descend_into_macros( let src = Source::new(file_id.into(), token); successors(Some(src), |token| { - let macro_call = token.ast.ancestors().find_map(ast::MacroCall::cast)?; + let macro_call = token.value.ancestors().find_map(ast::MacroCall::cast)?; let tt = macro_call.token_tree()?; - if !token.ast.text_range().is_subrange(&tt.syntax().text_range()) { + if !token.value.text_range().is_subrange(&tt.syntax().text_range()) { return None; } let source_analyzer = - hir::SourceAnalyzer::new(db, token.with_ast(token.ast.parent()).as_ref(), None); + hir::SourceAnalyzer::new(db, token.with_ast(token.value.parent()).as_ref(), None); let exp = source_analyzer.expand(db, ¯o_call)?; exp.map_token_down(db, token.as_ref()) }) diff --git a/crates/ra_ide_api/src/expand_macro.rs b/crates/ra_ide_api/src/expand_macro.rs index e9eb2a7fb8..2d478ec09b 100644 --- a/crates/ra_ide_api/src/expand_macro.rs +++ b/crates/ra_ide_api/src/expand_macro.rs @@ -46,7 +46,7 @@ fn expand_macro_recur( let mut replaces = FxHashMap::default(); for child in children.into_iter() { - let source = hir::Source::new(macro_file_id, source.ast); + let source = hir::Source::new(macro_file_id, source.value); let new_node = expand_macro_recur(db, source, &child)?; replaces.insert(child.syntax().clone().into(), new_node.into()); @@ -139,7 +139,7 @@ mod tests { } macro_rules! baz { () => { foo!(); } - } + } f<|>oo!(); "#, ); @@ -156,7 +156,7 @@ fn b(){} r#" //- /lib.rs macro_rules! foo { - () => { + () => { fn some_thing() -> u32 { let a = 0; a + 10 @@ -172,7 +172,7 @@ fn b(){} fn some_thing() -> u32 { let a = 0; a+10 -} +} "###); } } diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 3f16e95661..ed9d99a7f8 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -23,7 +23,7 @@ pub(crate) fn goto_definition( let token = descend_into_macros(db, position.file_id, token); let res = match_ast! { - match (token.ast.parent()) { + match (token.value.parent()) { ast::NameRef(name_ref) => { let navs = reference_definition(db, token.with_ast(&name_ref)).to_vec(); RangeInfo::new(name_ref.syntax().text_range(), navs.to_vec()) @@ -84,7 +84,7 @@ pub(crate) fn reference_definition( }; // Fallback index based approach: - let navs = crate::symbol_index::index_resolve(db, name_ref.ast) + let navs = crate::symbol_index::index_resolve(db, name_ref.value) .into_iter() .map(|s| s.to_nav(db)) .collect(); @@ -95,7 +95,7 @@ pub(crate) fn name_definition( db: &RootDatabase, name: Source<&ast::Name>, ) -> Option> { - let parent = name.ast.syntax().parent()?; + let parent = name.value.syntax().parent()?; if let Some(module) = ast::Module::cast(parent.clone()) { if module.has_semi() { @@ -116,7 +116,7 @@ pub(crate) fn name_definition( fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option { match_ast! { - match (node.ast) { + match (node.value) { ast::StructDef(it) => { Some(NavigationTarget::from_named( db, diff --git a/crates/ra_ide_api/src/goto_type_definition.rs b/crates/ra_ide_api/src/goto_type_definition.rs index 7d694e1f6e..6aeeefa1f0 100644 --- a/crates/ra_ide_api/src/goto_type_definition.rs +++ b/crates/ra_ide_api/src/goto_type_definition.rs @@ -16,7 +16,7 @@ pub(crate) fn goto_type_definition( let token = file.token_at_offset(position.offset).filter(|it| !it.kind().is_trivia()).next()?; let token = descend_into_macros(db, position.file_id, token); - let node = token.ast.ancestors().find_map(|token| { + let node = token.value.ancestors().find_map(|token| { token .ancestors() .find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some()) diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index 787b714b3a..e8a340ba4c 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs @@ -101,11 +101,11 @@ fn hover_text_from_name_kind( return match name_kind { Macro(it) => { let src = it.source(db); - hover_text(src.ast.doc_comment_text(), Some(macro_label(&src.ast))) + hover_text(src.value.doc_comment_text(), Some(macro_label(&src.value))) } Field(it) => { let src = it.source(db); - match src.ast { + match src.value { hir::FieldSource::Named(it) => hover_text(it.doc_comment_text(), it.short_label()), _ => None, } @@ -116,7 +116,7 @@ fn hover_text_from_name_kind( hir::AssocItem::TypeAlias(it) => from_def_source(db, it), }, Def(it) => match it { - hir::ModuleDef::Module(it) => match it.definition_source(db).ast { + hir::ModuleDef::Module(it) => match it.definition_source(db).value { hir::ModuleSource::Module(it) => { hover_text(it.doc_comment_text(), it.short_label()) } @@ -158,7 +158,7 @@ fn hover_text_from_name_kind( A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel, { let src = def.source(db); - hover_text(src.ast.doc_comment_text(), src.ast.short_label()) + hover_text(src.value.doc_comment_text(), src.value.short_label()) } } @@ -170,7 +170,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option { let mut no_fallback = false; if let Some(name_kind) = @@ -211,7 +211,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option(&syntax, position.offset) { @@ -42,11 +42,11 @@ fn impls_for_def( ) -> Option> { let ty = match node { ast::NominalDef::StructDef(def) => { - let src = hir::Source { file_id: position.file_id.into(), ast: def.clone() }; + let src = hir::Source { file_id: position.file_id.into(), value: def.clone() }; hir::Struct::from_source(db, src)?.ty(db) } ast::NominalDef::EnumDef(def) => { - let src = hir::Source { file_id: position.file_id.into(), ast: def.clone() }; + let src = hir::Source { file_id: position.file_id.into(), value: def.clone() }; hir::Enum::from_source(db, src)?.ty(db) } }; @@ -69,7 +69,7 @@ fn impls_for_trait( node: &ast::TraitDef, module: hir::Module, ) -> Option> { - let src = hir::Source { file_id: position.file_id.into(), ast: node.clone() }; + let src = hir::Source { file_id: position.file_id.into(), value: node.clone() }; let tr = hir::Trait::from_source(db, src)?; let krate = module.krate(); diff --git a/crates/ra_ide_api/src/parent_module.rs b/crates/ra_ide_api/src/parent_module.rs index 4c57566e2a..fa232a379f 100644 --- a/crates/ra_ide_api/src/parent_module.rs +++ b/crates/ra_ide_api/src/parent_module.rs @@ -10,7 +10,7 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec return Vec::new(), Some(it) => it, @@ -23,7 +23,8 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec Vec { let src = hir::ModuleSource::from_file_id(db, file_id); let module = - match hir::Module::from_definition(db, hir::Source { file_id: file_id.into(), ast: src }) { + match hir::Module::from_definition(db, hir::Source { file_id: file_id.into(), value: src }) + { Some(it) => it, None => return Vec::new(), }; diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs index ea9d20e715..333264540c 100644 --- a/crates/ra_ide_api/src/references/classify.rs +++ b/crates/ra_ide_api/src/references/classify.rs @@ -13,7 +13,7 @@ use crate::db::RootDatabase; pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Option { let _p = profile("classify_name"); - let parent = name.ast.syntax().parent()?; + let parent = name.value.syntax().parent()?; match_ast! { match parent { @@ -121,7 +121,7 @@ pub(crate) fn classify_name_ref( ) -> Option { let _p = profile("classify_name_ref"); - let parent = name_ref.ast.syntax().parent()?; + let parent = name_ref.value.syntax().parent()?; let analyzer = SourceAnalyzer::new(db, name_ref.map(|it| it.syntax()), None); if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { @@ -142,7 +142,7 @@ pub(crate) fn classify_name_ref( tested_by!(goto_definition_works_for_record_fields); if let Some(record_lit) = record_field.syntax().ancestors().find_map(ast::RecordLit::cast) { let variant_def = analyzer.resolve_record_literal(&record_lit)?; - let hir_path = Path::from_name_ref(name_ref.ast); + let hir_path = Path::from_name_ref(name_ref.value); let hir_name = hir_path.as_ident()?; let field = variant_def.field(db, hir_name)?; return Some(from_struct_field(db, field)); @@ -162,7 +162,7 @@ pub(crate) fn classify_name_ref( } } - let path = name_ref.ast.syntax().ancestors().find_map(ast::Path::cast)?; + let path = name_ref.value.syntax().ancestors().find_map(ast::Path::cast)?; let resolved = analyzer.resolve_path(db, &path)?; match resolved { PathResolution::Def(def) => Some(from_module_def(db, def, Some(container))), diff --git a/crates/ra_ide_api/src/references/name_definition.rs b/crates/ra_ide_api/src/references/name_definition.rs index ccd75278ae..aca23f79e2 100644 --- a/crates/ra_ide_api/src/references/name_definition.rs +++ b/crates/ra_ide_api/src/references/name_definition.rs @@ -32,9 +32,9 @@ pub(crate) struct NameDefinition { pub(super) fn from_assoc_item(db: &RootDatabase, item: AssocItem) -> NameDefinition { let container = item.module(db); let visibility = match item { - AssocItem::Function(f) => f.source(db).ast.visibility(), - AssocItem::Const(c) => c.source(db).ast.visibility(), - AssocItem::TypeAlias(a) => a.source(db).ast.visibility(), + AssocItem::Function(f) => f.source(db).value.visibility(), + AssocItem::Const(c) => c.source(db).value.visibility(), + AssocItem::TypeAlias(a) => a.source(db).value.visibility(), }; let kind = NameKind::AssocItem(item); NameDefinition { kind, container, visibility } @@ -45,8 +45,8 @@ pub(super) fn from_struct_field(db: &RootDatabase, field: StructField) -> NameDe let parent = field.parent_def(db); let container = parent.module(db); let visibility = match parent { - VariantDef::Struct(s) => s.source(db).ast.visibility(), - VariantDef::EnumVariant(e) => e.source(db).ast.parent_enum().visibility(), + VariantDef::Struct(s) => s.source(db).value.visibility(), + VariantDef::EnumVariant(e) => e.source(db).value.parent_enum().visibility(), }; NameDefinition { kind, container, visibility } } @@ -60,22 +60,22 @@ pub(super) fn from_module_def( let (container, visibility) = match def { ModuleDef::Module(it) => { let container = it.parent(db).or_else(|| Some(it)).unwrap(); - let visibility = it.declaration_source(db).and_then(|s| s.ast.visibility()); + let visibility = it.declaration_source(db).and_then(|s| s.value.visibility()); (container, visibility) } ModuleDef::EnumVariant(it) => { let container = it.module(db); - let visibility = it.source(db).ast.parent_enum().visibility(); + let visibility = it.source(db).value.parent_enum().visibility(); (container, visibility) } - ModuleDef::Function(it) => (it.module(db), it.source(db).ast.visibility()), - ModuleDef::Const(it) => (it.module(db), it.source(db).ast.visibility()), - ModuleDef::Static(it) => (it.module(db), it.source(db).ast.visibility()), - ModuleDef::Trait(it) => (it.module(db), it.source(db).ast.visibility()), - ModuleDef::TypeAlias(it) => (it.module(db), it.source(db).ast.visibility()), - ModuleDef::Adt(Adt::Struct(it)) => (it.module(db), it.source(db).ast.visibility()), - ModuleDef::Adt(Adt::Union(it)) => (it.module(db), it.source(db).ast.visibility()), - ModuleDef::Adt(Adt::Enum(it)) => (it.module(db), it.source(db).ast.visibility()), + ModuleDef::Function(it) => (it.module(db), it.source(db).value.visibility()), + ModuleDef::Const(it) => (it.module(db), it.source(db).value.visibility()), + ModuleDef::Static(it) => (it.module(db), it.source(db).value.visibility()), + ModuleDef::Trait(it) => (it.module(db), it.source(db).value.visibility()), + ModuleDef::TypeAlias(it) => (it.module(db), it.source(db).value.visibility()), + ModuleDef::Adt(Adt::Struct(it)) => (it.module(db), it.source(db).value.visibility()), + ModuleDef::Adt(Adt::Union(it)) => (it.module(db), it.source(db).value.visibility()), + ModuleDef::Adt(Adt::Enum(it)) => (it.module(db), it.source(db).value.visibility()), ModuleDef::BuiltinType(..) => (module.unwrap(), None), }; NameDefinition { kind, container, visibility } diff --git a/crates/ra_ide_api/src/references/rename.rs b/crates/ra_ide_api/src/references/rename.rs index 11f81cbb32..4ea372e6f0 100644 --- a/crates/ra_ide_api/src/references/rename.rs +++ b/crates/ra_ide_api/src/references/rename.rs @@ -55,11 +55,11 @@ fn rename_mod( ) -> Option { let mut source_file_edits = Vec::new(); let mut file_system_edits = Vec::new(); - let module_src = hir::Source { file_id: position.file_id.into(), ast: ast_module.clone() }; + let module_src = hir::Source { file_id: position.file_id.into(), value: ast_module.clone() }; if let Some(module) = hir::Module::from_declaration(db, module_src) { let src = module.definition_source(db); let file_id = src.file_id.original_file(db); - match src.ast { + match src.value { ModuleSource::SourceFile(..) => { let mod_path: RelativePathBuf = db.file_relative_path(file_id); // mod is defined in path/to/dir/mod.rs diff --git a/crates/ra_ide_api/src/references/search_scope.rs b/crates/ra_ide_api/src/references/search_scope.rs index 2907787c24..f5c9589f4d 100644 --- a/crates/ra_ide_api/src/references/search_scope.rs +++ b/crates/ra_ide_api/src/references/search_scope.rs @@ -73,9 +73,9 @@ impl NameDefinition { if let NameKind::Local(var) = self.kind { let range = match var.parent(db) { - DefWithBody::Function(f) => f.source(db).ast.syntax().text_range(), - DefWithBody::Const(c) => c.source(db).ast.syntax().text_range(), - DefWithBody::Static(s) => s.source(db).ast.syntax().text_range(), + DefWithBody::Function(f) => f.source(db).value.syntax().text_range(), + DefWithBody::Const(c) => c.source(db).value.syntax().text_range(), + DefWithBody::Static(s) => s.source(db).value.syntax().text_range(), }; let mut res = FxHashMap::default(); res.insert(file_id, Some(range)); @@ -91,7 +91,7 @@ impl NameDefinition { let parent_src = parent_module.definition_source(db); let file_id = parent_src.file_id.original_file(db); - match parent_src.ast { + match parent_src.value { ModuleSource::Module(m) => { let range = Some(m.syntax().text_range()); res.insert(file_id, range); @@ -135,7 +135,7 @@ impl NameDefinition { } let mut res = FxHashMap::default(); - let range = match module_src.ast { + let range = match module_src.value { ModuleSource::Module(m) => Some(m.syntax().text_range()), ModuleSource::SourceFile(_) => None, }; From 7020167aa23e9125ac1a58fe2e217d1a92140745 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 09:47:14 +0300 Subject: [PATCH 05/24] Cleanup imports --- xtask/Cargo.toml | 3 +++ xtask/src/main.rs | 7 +++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 77b9ae2b46..65cabf0053 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -5,6 +5,9 @@ version = "0.1.0" authors = ["rust-analyzer developers"] publish = false +[lib] +doctest = false + [dependencies] walkdir = "2.1.3" pico-args = "0.3.0" diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 663e281035..4b1f0c887d 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -9,11 +9,10 @@ //! `.cargo/config`. mod help; +use std::{env, fmt::Write, path::PathBuf, str}; + use anyhow::Context; -use core::fmt::Write; -use core::str; use pico_args::Arguments; -use std::{env, path::PathBuf}; use xtask::{ codegen::{self, Mode}, install_pre_commit_hook, reformat_staged_files, run, run_clippy, run_fuzzer, run_rustfmt, @@ -37,7 +36,7 @@ struct ServerOpt { } fn main() -> Result<()> { - if std::env::args().next().map(|it| it.contains("pre-commit")) == Some(true) { + if env::args().next().map(|it| it.contains("pre-commit")) == Some(true) { return reformat_staged_files(); } From 0e771915faf057ec4561224b75ec9b5be93d71c8 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 11:42:58 +0300 Subject: [PATCH 06/24] Allow non-path default type parameters --- crates/ra_hir/src/generics.rs | 11 ++++------- crates/ra_hir/src/ty/lower.rs | 4 +--- crates/ra_hir/src/ty/tests.rs | 24 ++++++++++++++++++++++++ crates/ra_syntax/src/ast/generated.rs | 7 +++++-- crates/ra_syntax/src/ast/traits.rs | 6 ------ crates/ra_syntax/src/grammar.ron | 5 ++++- 6 files changed, 38 insertions(+), 19 deletions(-) diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index 8925ba3a9f..78fab1a13a 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs @@ -5,12 +5,9 @@ use std::sync::Arc; -use hir_def::{ - path::Path, - type_ref::{TypeBound, TypeRef}, -}; +use hir_def::type_ref::{TypeBound, TypeRef}; use hir_expand::name::{self, AsName}; -use ra_syntax::ast::{self, DefaultTypeParamOwner, NameOwner, TypeBoundsOwner, TypeParamsOwner}; +use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; use crate::{ db::{AstDatabase, DefDatabase, HirDatabase}, @@ -24,7 +21,7 @@ pub struct GenericParam { // FIXME: give generic params proper IDs pub idx: u32, pub name: Name, - pub default: Option, + pub default: Option, } /// Data about the generic parameters of a function, struct, impl, etc. @@ -140,7 +137,7 @@ impl GenericParams { for (idx, type_param) in params.type_params().enumerate() { let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); // FIXME: Use `Path::from_src` - let default = type_param.default_type().and_then(|t| t.path()).and_then(Path::from_ast); + let default = type_param.default_type().map(TypeRef::from_ast); let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default }; self.params.push(param); diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index de3c56097b..03db386055 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs @@ -611,9 +611,7 @@ pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDef) -> let defaults = generic_params .params_including_parent() .into_iter() - .map(|p| { - p.default.as_ref().map_or(Ty::Unknown, |path| Ty::from_hir_path(db, &resolver, path)) - }) + .map(|p| p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(db, &resolver, t))) .collect(); Substs(defaults) diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index c1024d03c7..abfaffb5e2 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -1979,6 +1979,30 @@ fn test() { ); } +#[test] +fn infer_associated_method_generics_with_default_tuple_param() { + let t = type_at( + r#" +//- /main.rs +struct Gen { + val: T +} + +impl Gen { + pub fn make() -> Gen { + loop { } + } +} + +fn test() { + let a = Gen::make(); + a.val<|>; +} +"#, + ); + assert_eq!(t, "()"); +} + #[test] fn infer_associated_method_generics_without_args() { assert_snapshot!( diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 2b381dcdba..de506d7cda 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -3625,8 +3625,11 @@ impl AstNode for TypeParam { impl ast::NameOwner for TypeParam {} impl ast::AttrsOwner for TypeParam {} impl ast::TypeBoundsOwner for TypeParam {} -impl ast::DefaultTypeParamOwner for TypeParam {} -impl TypeParam {} +impl TypeParam { + pub fn default_type(&self) -> Option { + AstChildren::new(&self.syntax).next() + } +} #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TypeParamList { pub(crate) syntax: SyntaxNode, diff --git a/crates/ra_syntax/src/ast/traits.rs b/crates/ra_syntax/src/ast/traits.rs index c2b005886a..f99984fe0f 100644 --- a/crates/ra_syntax/src/ast/traits.rs +++ b/crates/ra_syntax/src/ast/traits.rs @@ -163,9 +163,3 @@ impl Iterator for CommentIter { self.iter.by_ref().find_map(|el| el.into_token().and_then(ast::Comment::cast)) } } - -pub trait DefaultTypeParamOwner: AstNode { - fn default_type(&self) -> Option { - child_opt(self) - } -} diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index 70d85a8e6a..88d1dc109b 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron @@ -587,7 +587,10 @@ Grammar( ("lifetime_params", "LifetimeParam" ), ] ), - "TypeParam": ( traits: ["NameOwner", "AttrsOwner", "TypeBoundsOwner", "DefaultTypeParamOwner"] ), + "TypeParam": ( + options: [("default_type", "TypeRef")], + traits: ["NameOwner", "AttrsOwner", "TypeBoundsOwner"], + ), "LifetimeParam": ( traits: ["AttrsOwner"], ), From e1a6e38767c1e47e5e88a97a9ef5b4547390803c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 12:25:02 +0300 Subject: [PATCH 07/24] Move Generics to hir_def --- crates/ra_hir/src/db.rs | 2 +- crates/ra_hir/src/from_id.rs | 44 +++++++- crates/ra_hir/src/generics.rs | 182 +++--------------------------- crates/ra_hir/src/resolve.rs | 2 +- crates/ra_hir_def/src/generics.rs | 163 ++++++++++++++++++++++++++ crates/ra_hir_def/src/lib.rs | 24 ++++ 6 files changed, 247 insertions(+), 170 deletions(-) create mode 100644 crates/ra_hir_def/src/generics.rs diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index d75d71d665..0d35014a0f 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -43,7 +43,7 @@ pub trait DefDatabase: HirDebugDatabase + DefDatabase2 { #[salsa::invoke(crate::traits::TraitItemsIndex::trait_items_index)] fn trait_items_index(&self, module: Module) -> crate::traits::TraitItemsIndex; - #[salsa::invoke(crate::generics::GenericParams::generic_params_query)] + #[salsa::invoke(crate::generics::generic_params_query)] fn generic_params(&self, def: GenericDef) -> Arc; #[salsa::invoke(FnData::fn_data_query)] diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs index f2203e9953..b7692d4073 100644 --- a/crates/ra_hir/src/from_id.rs +++ b/crates/ra_hir/src/from_id.rs @@ -3,9 +3,9 @@ //! It's unclear if we need this long-term, but it's definitelly useful while we //! are splitting the hir. -use hir_def::{AdtId, AssocItemId, DefWithBodyId, EnumVariantId, ModuleDefId}; +use hir_def::{AdtId, AssocItemId, DefWithBodyId, EnumVariantId, GenericDefId, ModuleDefId}; -use crate::{Adt, AssocItem, DefWithBody, EnumVariant, ModuleDef}; +use crate::{Adt, AssocItem, DefWithBody, EnumVariant, GenericDef, ModuleDef}; macro_rules! from_id { ($(($id:path, $ty:path)),*) => {$( @@ -41,6 +41,16 @@ impl From for Adt { } } +impl From for AdtId { + fn from(id: Adt) -> Self { + match id { + Adt::Struct(it) => AdtId::StructId(it.id), + Adt::Union(it) => AdtId::UnionId(it.id), + Adt::Enum(it) => AdtId::EnumId(it.id), + } + } +} + impl From for EnumVariant { fn from(id: EnumVariantId) -> Self { EnumVariant { parent: id.parent.into(), id: id.local_id } @@ -82,3 +92,33 @@ impl From for AssocItem { } } } + +impl From for GenericDefId { + fn from(def: GenericDef) -> Self { + match def { + GenericDef::Function(it) => GenericDefId::FunctionId(it.id), + GenericDef::Adt(it) => GenericDefId::AdtId(it.into()), + GenericDef::Trait(it) => GenericDefId::TraitId(it.id), + GenericDef::TypeAlias(it) => GenericDefId::TypeAliasId(it.id), + GenericDef::ImplBlock(it) => GenericDefId::ImplId(it.id), + GenericDef::EnumVariant(it) => { + GenericDefId::EnumVariantId(EnumVariantId { parent: it.parent.id, local_id: it.id }) + } + GenericDef::Const(it) => GenericDefId::ConstId(it.id), + } + } +} + +impl From for GenericDef { + fn from(def: GenericDefId) -> Self { + match def { + GenericDefId::FunctionId(it) => GenericDef::Function(it.into()), + GenericDefId::AdtId(it) => GenericDef::Adt(it.into()), + GenericDefId::TraitId(it) => GenericDef::Trait(it.into()), + GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()), + GenericDefId::ImplId(it) => GenericDef::ImplBlock(it.into()), + GenericDefId::EnumVariantId(it) => GenericDef::EnumVariant(it.into()), + GenericDefId::ConstId(it) => GenericDef::Const(it.into()), + } + } +} diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index 78fab1a13a..caedb90e6a 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs @@ -1,47 +1,12 @@ -//! Many kinds of items or constructs can have generic parameters: functions, -//! structs, impls, traits, etc. This module provides a common HIR for these -//! generic parameters. See also the `Generics` type and the `generics_of` query -//! in rustc. - +//! Temp module to wrap hir_def::generics use std::sync::Arc; -use hir_def::type_ref::{TypeBound, TypeRef}; -use hir_expand::name::{self, AsName}; -use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; - use crate::{ db::{AstDatabase, DefDatabase, HirDatabase}, - Adt, Const, Container, Enum, EnumVariant, Function, HasSource, ImplBlock, Name, Struct, Trait, - TypeAlias, Union, + Adt, Const, Container, Enum, EnumVariant, Function, ImplBlock, Struct, Trait, TypeAlias, Union, }; -/// Data about a generic parameter (to a function, struct, impl, ...). -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct GenericParam { - // FIXME: give generic params proper IDs - pub idx: u32, - pub name: Name, - pub default: Option, -} - -/// Data about the generic parameters of a function, struct, impl, etc. -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct GenericParams { - pub(crate) def: GenericDef, - pub(crate) parent_params: Option>, - pub(crate) params: Vec, - pub(crate) where_predicates: Vec, -} - -/// A single predicate from a where clause, i.e. `where Type: Trait`. Combined -/// where clauses like `where T: Foo + Bar` are turned into multiple of these. -/// It might still result in multiple actual predicates though, because of -/// associated type bindings like `Iterator`. -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct WherePredicate { - pub(crate) type_ref: TypeRef, - pub(crate) bound: TypeBound, -} +pub use hir_def::generics::{GenericParam, GenericParams, WherePredicate}; #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] pub enum GenericDef { @@ -66,134 +31,19 @@ impl_froms!( Const ); -impl GenericParams { - pub(crate) fn generic_params_query( - db: &(impl DefDatabase + AstDatabase), - def: GenericDef, - ) -> Arc { - let parent = match def { - GenericDef::Function(it) => it.container(db).map(GenericDef::from), - GenericDef::TypeAlias(it) => it.container(db).map(GenericDef::from), - GenericDef::Const(it) => it.container(db).map(GenericDef::from), - GenericDef::EnumVariant(it) => Some(it.parent_enum(db).into()), - GenericDef::Adt(_) | GenericDef::Trait(_) => None, - GenericDef::ImplBlock(_) => None, - }; - let mut generics = GenericParams { - def, - params: Vec::new(), - parent_params: parent.map(|p| db.generic_params(p)), - where_predicates: Vec::new(), - }; - let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; - // FIXME: add `: Sized` bound for everything except for `Self` in traits - match def { - GenericDef::Function(it) => generics.fill(&it.source(db).value, start), - GenericDef::Adt(Adt::Struct(it)) => generics.fill(&it.source(db).value, start), - GenericDef::Adt(Adt::Union(it)) => generics.fill(&it.source(db).value, start), - GenericDef::Adt(Adt::Enum(it)) => generics.fill(&it.source(db).value, start), - GenericDef::Trait(it) => { - // traits get the Self type as an implicit first type parameter - generics.params.push(GenericParam { - idx: start, - name: name::SELF_TYPE, - default: None, - }); - generics.fill(&it.source(db).value, start + 1); - // add super traits as bounds on Self - // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar - let self_param = TypeRef::Path(name::SELF_TYPE.into()); - generics.fill_bounds(&it.source(db).value, self_param); - } - GenericDef::TypeAlias(it) => generics.fill(&it.source(db).value, start), - // Note that we don't add `Self` here: in `impl`s, `Self` is not a - // type-parameter, but rather is a type-alias for impl's target - // type, so this is handled by the resolver. - GenericDef::ImplBlock(it) => generics.fill(&it.source(db).value, start), - GenericDef::EnumVariant(_) | GenericDef::Const(_) => {} - } - - Arc::new(generics) - } - - fn fill(&mut self, node: &impl TypeParamsOwner, start: u32) { - if let Some(params) = node.type_param_list() { - self.fill_params(params, start) - } - if let Some(where_clause) = node.where_clause() { - self.fill_where_predicates(where_clause); - } - } - - fn fill_bounds(&mut self, node: &impl ast::TypeBoundsOwner, type_ref: TypeRef) { - for bound in - node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) - { - self.add_where_predicate_from_bound(bound, type_ref.clone()); - } - } - - fn fill_params(&mut self, params: ast::TypeParamList, start: u32) { - for (idx, type_param) in params.type_params().enumerate() { - let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); - // FIXME: Use `Path::from_src` - let default = type_param.default_type().map(TypeRef::from_ast); - - let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default }; - self.params.push(param); - - let type_ref = TypeRef::Path(name.into()); - self.fill_bounds(&type_param, type_ref); - } - } - - fn fill_where_predicates(&mut self, where_clause: ast::WhereClause) { - for pred in where_clause.predicates() { - let type_ref = match pred.type_ref() { - Some(type_ref) => type_ref, - None => continue, - }; - let type_ref = TypeRef::from_ast(type_ref); - for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { - self.add_where_predicate_from_bound(bound, type_ref.clone()); - } - } - } - - fn add_where_predicate_from_bound(&mut self, bound: ast::TypeBound, type_ref: TypeRef) { - if bound.has_question_mark() { - // FIXME: remove this bound - return; - } - let bound = TypeBound::from_ast(bound); - self.where_predicates.push(WherePredicate { type_ref, bound }); - } - - pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { - self.params.iter().find(|p| &p.name == name) - } - - pub fn count_parent_params(&self) -> usize { - self.parent_params.as_ref().map(|p| p.count_params_including_parent()).unwrap_or(0) - } - - pub fn count_params_including_parent(&self) -> usize { - let parent_count = self.count_parent_params(); - parent_count + self.params.len() - } - - fn for_each_param<'a>(&'a self, f: &mut impl FnMut(&'a GenericParam)) { - if let Some(parent) = &self.parent_params { - parent.for_each_param(f); - } - self.params.iter().for_each(f); - } - - pub fn params_including_parent(&self) -> Vec<&GenericParam> { - let mut vec = Vec::with_capacity(self.count_params_including_parent()); - self.for_each_param(&mut |p| vec.push(p)); - vec - } +pub(crate) fn generic_params_query( + db: &(impl DefDatabase + AstDatabase), + def: GenericDef, +) -> Arc { + let parent = match def { + GenericDef::Function(it) => it.container(db).map(GenericDef::from), + GenericDef::TypeAlias(it) => it.container(db).map(GenericDef::from), + GenericDef::Const(it) => it.container(db).map(GenericDef::from), + GenericDef::EnumVariant(it) => Some(it.parent_enum(db).into()), + GenericDef::Adt(_) | GenericDef::Trait(_) => None, + GenericDef::ImplBlock(_) => None, + }; + Arc::new(GenericParams::new(db, def.into(), parent.map(|it| db.generic_params(it)))) } impl GenericDef { diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index 79b92180a6..a2fa0bb79e 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs @@ -369,7 +369,7 @@ impl Resolver { pub(crate) fn generic_def(&self) -> Option { self.scopes.iter().find_map(|scope| match scope { - Scope::GenericParams(params) => Some(params.def), + Scope::GenericParams(params) => Some(params.def.into()), _ => None, }) } diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs new file mode 100644 index 0000000000..4adfc16bbb --- /dev/null +++ b/crates/ra_hir_def/src/generics.rs @@ -0,0 +1,163 @@ +//! Many kinds of items or constructs can have generic parameters: functions, +//! structs, impls, traits, etc. This module provides a common HIR for these +//! generic parameters. See also the `Generics` type and the `generics_of` query +//! in rustc. +use std::sync::Arc; + +use hir_expand::name::{self, AsName, Name}; + +use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; + +use crate::{ + db::DefDatabase2, + type_ref::{TypeBound, TypeRef}, + AdtId, AstItemDef, GenericDefId, +}; + +/// Data about a generic parameter (to a function, struct, impl, ...). +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct GenericParam { + // FIXME: give generic params proper IDs + pub idx: u32, + pub name: Name, + pub default: Option, +} + +/// Data about the generic parameters of a function, struct, impl, etc. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct GenericParams { + pub def: GenericDefId, + pub parent_params: Option>, + pub params: Vec, + pub where_predicates: Vec, +} + +/// A single predicate from a where clause, i.e. `where Type: Trait`. Combined +/// where clauses like `where T: Foo + Bar` are turned into multiple of these. +/// It might still result in multiple actual predicates though, because of +/// associated type bindings like `Iterator`. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct WherePredicate { + pub type_ref: TypeRef, + pub bound: TypeBound, +} + +impl GenericParams { + pub fn new( + db: &impl DefDatabase2, + def: GenericDefId, + parent_params: Option>, + ) -> GenericParams { + let mut generics = + GenericParams { def, params: Vec::new(), parent_params, where_predicates: Vec::new() }; + let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; + // FIXME: add `: Sized` bound for everything except for `Self` in traits + match def { + GenericDefId::FunctionId(it) => generics.fill(&it.source(db).value, start), + GenericDefId::AdtId(AdtId::StructId(it)) => { + generics.fill(&it.0.source(db).value, start) + } + GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.0.source(db).value, start), + GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value, start), + GenericDefId::TraitId(it) => { + // traits get the Self type as an implicit first type parameter + generics.params.push(GenericParam { + idx: start, + name: name::SELF_TYPE, + default: None, + }); + generics.fill(&it.source(db).value, start + 1); + // add super traits as bounds on Self + // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar + let self_param = TypeRef::Path(name::SELF_TYPE.into()); + generics.fill_bounds(&it.source(db).value, self_param); + } + GenericDefId::TypeAliasId(it) => generics.fill(&it.source(db).value, start), + // Note that we don't add `Self` here: in `impl`s, `Self` is not a + // type-parameter, but rather is a type-alias for impl's target + // type, so this is handled by the resolver. + GenericDefId::ImplId(it) => generics.fill(&it.source(db).value, start), + GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {} + } + + generics + } + + fn fill(&mut self, node: &impl TypeParamsOwner, start: u32) { + if let Some(params) = node.type_param_list() { + self.fill_params(params, start) + } + if let Some(where_clause) = node.where_clause() { + self.fill_where_predicates(where_clause); + } + } + + fn fill_bounds(&mut self, node: &impl ast::TypeBoundsOwner, type_ref: TypeRef) { + for bound in + node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) + { + self.add_where_predicate_from_bound(bound, type_ref.clone()); + } + } + + fn fill_params(&mut self, params: ast::TypeParamList, start: u32) { + for (idx, type_param) in params.type_params().enumerate() { + let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); + // FIXME: Use `Path::from_src` + let default = type_param.default_type().map(TypeRef::from_ast); + let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default }; + self.params.push(param); + + let type_ref = TypeRef::Path(name.into()); + self.fill_bounds(&type_param, type_ref); + } + } + + fn fill_where_predicates(&mut self, where_clause: ast::WhereClause) { + for pred in where_clause.predicates() { + let type_ref = match pred.type_ref() { + Some(type_ref) => type_ref, + None => continue, + }; + let type_ref = TypeRef::from_ast(type_ref); + for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { + self.add_where_predicate_from_bound(bound, type_ref.clone()); + } + } + } + + fn add_where_predicate_from_bound(&mut self, bound: ast::TypeBound, type_ref: TypeRef) { + if bound.has_question_mark() { + // FIXME: remove this bound + return; + } + let bound = TypeBound::from_ast(bound); + self.where_predicates.push(WherePredicate { type_ref, bound }); + } + + pub fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { + self.params.iter().find(|p| &p.name == name) + } + + pub fn count_parent_params(&self) -> usize { + self.parent_params.as_ref().map(|p| p.count_params_including_parent()).unwrap_or(0) + } + + pub fn count_params_including_parent(&self) -> usize { + let parent_count = self.count_parent_params(); + parent_count + self.params.len() + } + + fn for_each_param<'a>(&'a self, f: &mut impl FnMut(&'a GenericParam)) { + if let Some(parent) = &self.parent_params { + parent.for_each_param(f); + } + self.params.iter().for_each(f); + } + + pub fn params_including_parent(&self) -> Vec<&GenericParam> { + let mut vec = Vec::with_capacity(self.count_params_including_parent()); + self.for_each_param(&mut |p| vec.push(p)); + vec + } +} diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 50caf4f836..dffc82ff8c 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -17,6 +17,7 @@ pub mod imp; pub mod diagnostics; pub mod expr; pub mod body; +pub mod generics; #[cfg(test)] mod test_db; @@ -408,3 +409,26 @@ pub enum AssocItemId { // require not implementing From, and instead having some checked way of // casting them, and somehow making the constructors private, which would be annoying. impl_froms!(AssocItemId: FunctionId, ConstId, TypeAliasId); + +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +pub enum GenericDefId { + FunctionId(FunctionId), + AdtId(AdtId), + TraitId(TraitId), + TypeAliasId(TypeAliasId), + ImplId(ImplId), + // enum variants cannot have generics themselves, but their parent enums + // can, and this makes some code easier to write + EnumVariantId(EnumVariantId), + // consts can have type parameters from their parents (i.e. associated consts of traits) + ConstId(ConstId), +} +impl_froms!( + GenericDefId: FunctionId, + AdtId(StructId, EnumId, UnionId), + TraitId, + TypeAliasId, + ImplId, + EnumVariantId, + ConstId +); From 51baaf298d4ac56036062786bf070aeab7ab8e79 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 13:09:21 +0300 Subject: [PATCH 08/24] Rename with_ast -> with_value --- crates/ra_hir/src/source_binder.rs | 12 +++---- crates/ra_hir_expand/src/lib.rs | 8 ++--- .../src/display/navigation_target.rs | 10 +++--- crates/ra_ide_api/src/expand.rs | 4 +-- crates/ra_ide_api/src/goto_definition.rs | 30 ++++++++--------- crates/ra_ide_api/src/goto_type_definition.rs | 2 +- crates/ra_ide_api/src/hover.rs | 4 +-- crates/ra_ide_api/src/references/classify.rs | 32 +++++++++---------- 8 files changed, 51 insertions(+), 51 deletions(-) diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 471b0b0891..a1c1daacdb 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -33,19 +33,19 @@ fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) - match_ast! { match (node.value) { ast::Module(it) => { - let src = node.with_ast(it); + let src = node.with_value(it); Some(crate::Module::from_declaration(db, src)?.resolver(db)) }, ast::SourceFile(it) => { - let src = node.with_ast(crate::ModuleSource::SourceFile(it)); + let src = node.with_value(crate::ModuleSource::SourceFile(it)); Some(crate::Module::from_definition(db, src)?.resolver(db)) }, ast::StructDef(it) => { - let src = node.with_ast(it); + let src = node.with_value(it); Some(Struct::from_source(db, src)?.resolver(db)) }, ast::EnumDef(it) => { - let src = node.with_ast(it); + let src = node.with_value(it); Some(Enum::from_source(db, src)?.resolver(db)) }, _ => match node.value.kind() { @@ -157,7 +157,7 @@ impl SourceAnalyzer { let scopes = def.expr_scopes(db); let scope = match offset { None => scope_for(&scopes, &source_map, node), - Some(offset) => scope_for_offset(&scopes, &source_map, node.with_ast(offset)), + Some(offset) => scope_for_offset(&scopes, &source_map, node.with_value(offset)), }; let resolver = expr::resolver_for_scope(db, def, scope); SourceAnalyzer { @@ -173,7 +173,7 @@ impl SourceAnalyzer { resolver: node .value .ancestors() - .find_map(|it| try_get_resolver_for_node(db, node.with_ast(&it))) + .find_map(|it| try_get_resolver_for_node(db, node.with_value(&it))) .unwrap_or_default(), body_owner: None, body_source_map: None, diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index 6ca4bc7a39..1389f64ce9 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs @@ -174,7 +174,7 @@ impl ExpansionInfo { let token = algo::find_covering_element(&self.expanded.value, range).into_token()?; - Some(self.expanded.with_ast(token)) + Some(self.expanded.with_value(token)) } pub fn map_token_up(&self, token: Source<&SyntaxToken>) -> Option> { @@ -192,7 +192,7 @@ impl ExpansionInfo { range + tt.value.syntax().text_range().start(), ) .into_token()?; - Some(tt.with_ast(token)) + Some(tt.with_value(token)) } } @@ -259,7 +259,7 @@ impl Source { } // Similarly, naming here is stupid... - pub fn with_ast(&self, value: U) -> Source { + pub fn with_value(&self, value: U) -> Source { Source::new(self.file_id, value) } @@ -267,7 +267,7 @@ impl Source { Source::new(self.file_id, f(self.value)) } pub fn as_ref(&self) -> Source<&T> { - self.with_ast(&self.value) + self.with_value(&self.value) } pub fn file_syntax(&self, db: &impl db::AstDatabase) -> SyntaxNode { db.parse_or_expand(self.file_id).expect("source created from invalid file") diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs index 50accafd03..6ac60722b9 100644 --- a/crates/ra_ide_api/src/display/navigation_target.rs +++ b/crates/ra_ide_api/src/display/navigation_target.rs @@ -148,7 +148,7 @@ impl NavigationTarget { //FIXME: use `_` instead of empty string let name = node.value.name().map(|it| it.text().clone()).unwrap_or_default(); let focus_range = - node.value.name().map(|it| original_range(db, node.with_ast(it.syntax())).range); + node.value.name().map(|it| original_range(db, node.with_value(it.syntax())).range); let frange = original_range(db, node.map(|it| it.syntax())); NavigationTarget::from_syntax( @@ -232,7 +232,7 @@ impl ToNav for hir::Module { let name = self.name(db).map(|it| it.to_string().into()).unwrap_or_default(); match &src.value { ModuleSource::SourceFile(node) => { - let frange = original_range(db, src.with_ast(node.syntax())); + let frange = original_range(db, src.with_value(node.syntax())); NavigationTarget::from_syntax( frange.file_id, @@ -245,7 +245,7 @@ impl ToNav for hir::Module { ) } ModuleSource::Module(node) => { - let frange = original_range(db, src.with_ast(node.syntax())); + let frange = original_range(db, src.with_value(node.syntax())); NavigationTarget::from_syntax( frange.file_id, @@ -285,12 +285,12 @@ impl ToNav for hir::StructField { match &src.value { FieldSource::Named(it) => NavigationTarget::from_named( db, - src.with_ast(it), + src.with_value(it), it.doc_comment_text(), it.short_label(), ), FieldSource::Pos(it) => { - let frange = original_range(db, src.with_ast(it.syntax())); + let frange = original_range(db, src.with_value(it.syntax())); NavigationTarget::from_syntax( frange.file_id, "".into(), diff --git a/crates/ra_ide_api/src/expand.rs b/crates/ra_ide_api/src/expand.rs index 0228bced90..0ad125a9e3 100644 --- a/crates/ra_ide_api/src/expand.rs +++ b/crates/ra_ide_api/src/expand.rs @@ -28,7 +28,7 @@ pub(crate) fn original_range(db: &RootDatabase, node: Source<&SyntaxNode>) -> Fi .value .descendants_with_tokens() .filter_map(|it| it.into_token()) - .find_map(|it| expansion.map_token_up(node.with_ast(&it))); + .find_map(|it| expansion.map_token_up(node.with_value(&it))); match token { Some(it) => { @@ -54,7 +54,7 @@ pub(crate) fn descend_into_macros( return None; } let source_analyzer = - hir::SourceAnalyzer::new(db, token.with_ast(token.value.parent()).as_ref(), None); + hir::SourceAnalyzer::new(db, token.with_value(token.value.parent()).as_ref(), None); let exp = source_analyzer.expand(db, ¯o_call)?; exp.map_token_down(db, token.as_ref()) }) diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index ed9d99a7f8..b6c72efdff 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -25,11 +25,11 @@ pub(crate) fn goto_definition( let res = match_ast! { match (token.value.parent()) { ast::NameRef(name_ref) => { - let navs = reference_definition(db, token.with_ast(&name_ref)).to_vec(); + let navs = reference_definition(db, token.with_value(&name_ref)).to_vec(); RangeInfo::new(name_ref.syntax().text_range(), navs.to_vec()) }, ast::Name(name) => { - let navs = name_definition(db, token.with_ast(&name))?; + let navs = name_definition(db, token.with_value(&name))?; RangeInfo::new(name.syntax().text_range(), navs) }, @@ -99,7 +99,7 @@ pub(crate) fn name_definition( if let Some(module) = ast::Module::cast(parent.clone()) { if module.has_semi() { - let src = name.with_ast(module); + let src = name.with_value(module); if let Some(child_module) = hir::Module::from_declaration(db, src) { let nav = child_module.to_nav(db); return Some(vec![nav]); @@ -107,7 +107,7 @@ pub(crate) fn name_definition( } } - if let Some(nav) = named_target(db, name.with_ast(&parent)) { + if let Some(nav) = named_target(db, name.with_value(&parent)) { return Some(vec![nav]); } @@ -120,7 +120,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option { Some(NavigationTarget::from_named( db, - node.with_ast(&it), + node.with_value(&it), it.doc_comment_text(), it.short_label(), )) @@ -128,7 +128,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option { Some(NavigationTarget::from_named( db, - node.with_ast(&it), + node.with_value(&it), it.doc_comment_text(), it.short_label(), )) @@ -136,7 +136,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option { Some(NavigationTarget::from_named( db, - node.with_ast(&it), + node.with_value(&it), it.doc_comment_text(), it.short_label(), )) @@ -144,7 +144,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option { Some(NavigationTarget::from_named( db, - node.with_ast(&it), + node.with_value(&it), it.doc_comment_text(), it.short_label(), )) @@ -152,7 +152,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option { Some(NavigationTarget::from_named( db, - node.with_ast(&it), + node.with_value(&it), it.doc_comment_text(), it.short_label(), )) @@ -160,7 +160,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option { Some(NavigationTarget::from_named( db, - node.with_ast(&it), + node.with_value(&it), it.doc_comment_text(), it.short_label(), )) @@ -168,7 +168,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option { Some(NavigationTarget::from_named( db, - node.with_ast(&it), + node.with_value(&it), it.doc_comment_text(), it.short_label(), )) @@ -176,7 +176,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option { Some(NavigationTarget::from_named( db, - node.with_ast(&it), + node.with_value(&it), it.doc_comment_text(), it.short_label(), )) @@ -184,7 +184,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option { Some(NavigationTarget::from_named( db, - node.with_ast(&it), + node.with_value(&it), it.doc_comment_text(), it.short_label(), )) @@ -192,7 +192,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option { Some(NavigationTarget::from_named( db, - node.with_ast(&it), + node.with_value(&it), it.doc_comment_text(), it.short_label(), )) @@ -200,7 +200,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option { Some(NavigationTarget::from_named( db, - node.with_ast(&it), + node.with_value(&it), it.doc_comment_text(), None, )) diff --git a/crates/ra_ide_api/src/goto_type_definition.rs b/crates/ra_ide_api/src/goto_type_definition.rs index 6aeeefa1f0..28a83a3e2a 100644 --- a/crates/ra_ide_api/src/goto_type_definition.rs +++ b/crates/ra_ide_api/src/goto_type_definition.rs @@ -22,7 +22,7 @@ pub(crate) fn goto_type_definition( .find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some()) })?; - let analyzer = hir::SourceAnalyzer::new(db, token.with_ast(&node), None); + let analyzer = hir::SourceAnalyzer::new(db, token.with_value(&node), None); let ty: hir::Ty = if let Some(ty) = ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e)) diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index e8a340ba4c..ae87ab9f91 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs @@ -174,7 +174,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option { let mut no_fallback = false; if let Some(name_kind) = - classify_name_ref(db, token.with_ast(&name_ref)).map(|d| d.kind) + classify_name_ref(db, token.with_value(&name_ref)).map(|d| d.kind) { res.extend(hover_text_from_name_kind(db, name_kind, &mut no_fallback)) } @@ -196,7 +196,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option { - if let Some(name_kind) = classify_name(db, token.with_ast(&name)).map(|d| d.kind) { + if let Some(name_kind) = classify_name(db, token.with_value(&name)).map(|d| d.kind) { res.extend(hover_text_from_name_kind(db, name_kind, &mut true)); } diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs index 333264540c..4a4b030f89 100644 --- a/crates/ra_ide_api/src/references/classify.rs +++ b/crates/ra_ide_api/src/references/classify.rs @@ -18,7 +18,7 @@ pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Opti match_ast! { match parent { ast::BindPat(it) => { - let src = name.with_ast(it); + let src = name.with_value(it); let local = hir::Local::from_source(db, src)?; Some(NameDefinition { visibility: None, @@ -28,7 +28,7 @@ pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Opti }, ast::RecordFieldDef(it) => { let ast = hir::FieldSource::Named(it); - let src = name.with_ast(ast); + let src = name.with_value(ast); let field = hir::StructField::from_source(db, src)?; Some(from_struct_field(db, field)) }, @@ -36,42 +36,42 @@ pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Opti let def = { if !it.has_semi() { let ast = hir::ModuleSource::Module(it); - let src = name.with_ast(ast); + let src = name.with_value(ast); hir::Module::from_definition(db, src) } else { - let src = name.with_ast(it); + let src = name.with_value(it); hir::Module::from_declaration(db, src) } }?; Some(from_module_def(db, def.into(), None)) }, ast::StructDef(it) => { - let src = name.with_ast(it); + let src = name.with_value(it); let def = hir::Struct::from_source(db, src)?; Some(from_module_def(db, def.into(), None)) }, ast::EnumDef(it) => { - let src = name.with_ast(it); + let src = name.with_value(it); let def = hir::Enum::from_source(db, src)?; Some(from_module_def(db, def.into(), None)) }, ast::TraitDef(it) => { - let src = name.with_ast(it); + let src = name.with_value(it); let def = hir::Trait::from_source(db, src)?; Some(from_module_def(db, def.into(), None)) }, ast::StaticDef(it) => { - let src = name.with_ast(it); + let src = name.with_value(it); let def = hir::Static::from_source(db, src)?; Some(from_module_def(db, def.into(), None)) }, ast::EnumVariant(it) => { - let src = name.with_ast(it); + let src = name.with_value(it); let def = hir::EnumVariant::from_source(db, src)?; Some(from_module_def(db, def.into(), None)) }, ast::FnDef(it) => { - let src = name.with_ast(it); + let src = name.with_value(it); let def = hir::Function::from_source(db, src)?; if parent.parent().and_then(ast::ItemList::cast).is_some() { Some(from_assoc_item(db, def.into())) @@ -80,7 +80,7 @@ pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Opti } }, ast::ConstDef(it) => { - let src = name.with_ast(it); + let src = name.with_value(it); let def = hir::Const::from_source(db, src)?; if parent.parent().and_then(ast::ItemList::cast).is_some() { Some(from_assoc_item(db, def.into())) @@ -89,7 +89,7 @@ pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Opti } }, ast::TypeAliasDef(it) => { - let src = name.with_ast(it); + let src = name.with_value(it); let def = hir::TypeAlias::from_source(db, src)?; if parent.parent().and_then(ast::ItemList::cast).is_some() { Some(from_assoc_item(db, def.into())) @@ -98,11 +98,11 @@ pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Opti } }, ast::MacroCall(it) => { - let src = name.with_ast(it); + let src = name.with_value(it); let def = hir::MacroDef::from_source(db, src.clone())?; let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); - let module = Module::from_definition(db, src.with_ast(module_src))?; + let module = Module::from_definition(db, src.with_value(module_src))?; Some(NameDefinition { visibility: None, @@ -149,9 +149,9 @@ pub(crate) fn classify_name_ref( } } - let ast = ModuleSource::from_child_node(db, name_ref.with_ast(&parent)); + let ast = ModuleSource::from_child_node(db, name_ref.with_value(&parent)); // FIXME: find correct container and visibility for each case - let container = Module::from_definition(db, name_ref.with_ast(ast))?; + let container = Module::from_definition(db, name_ref.with_value(ast))?; let visibility = None; if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { From 06fa3d8389c833b01f482bf35b0f850e627612b9 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 14:22:06 +0300 Subject: [PATCH 09/24] Move traits to hir_def --- crates/ra_hir/src/code_model.rs | 32 ++++----- crates/ra_hir/src/db.rs | 10 +-- crates/ra_hir/src/lib.rs | 1 - crates/ra_hir/src/traits.rs | 82 ---------------------- crates/ra_hir/src/ty/method_resolution.rs | 6 +- crates/ra_hir_def/src/db.rs | 11 ++- crates/ra_hir_def/src/{imp.rs => impls.rs} | 0 crates/ra_hir_def/src/lib.rs | 3 +- crates/ra_hir_def/src/nameres.rs | 8 +++ crates/ra_hir_def/src/traits.rs | 67 ++++++++++++++++++ 10 files changed, 103 insertions(+), 117 deletions(-) delete mode 100644 crates/ra_hir/src/traits.rs rename crates/ra_hir_def/src/{imp.rs => impls.rs} (100%) create mode 100644 crates/ra_hir_def/src/traits.rs diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index cb990f4e23..f436d5d5e5 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -10,8 +10,9 @@ use hir_def::{ adt::VariantData, body::scope::ExprScopes, builtin_type::BuiltinType, + traits::TraitData, type_ref::{Mutability, TypeRef}, - CrateModuleId, ImplId, LocalEnumVariantId, LocalStructFieldId, ModuleId, UnionId, + AssocItemId, CrateModuleId, ImplId, LocalEnumVariantId, LocalStructFieldId, ModuleId, UnionId, }; use hir_expand::{ diagnostics::DiagnosticSink, @@ -30,7 +31,6 @@ use crate::{ TypeAliasId, }, resolve::{Resolver, Scope, TypeNs}, - traits::TraitData, ty::{InferenceResult, Namespace, TraitRef}, Either, HasSource, ImportId, Name, ScopeDef, Source, Ty, }; @@ -230,15 +230,7 @@ impl Module { pub fn declarations(self, db: &impl DefDatabase) -> Vec { let def_map = db.crate_def_map(self.id.krate); - def_map[self.id.module_id] - .scope - .entries() - .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None }) - .flat_map(|per_ns| { - per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter()) - }) - .map(ModuleDef::from) - .collect() + def_map[self.id.module_id].scope.declarations().map(ModuleDef::from).collect() } pub fn impl_blocks(self, db: &impl DefDatabase) -> Vec { @@ -693,7 +685,7 @@ impl Function { /// The containing trait, if this is a trait method definition. pub fn parent_trait(self, db: &impl DefDatabase) -> Option { - db.trait_items_index(self.module(db)).get_parent_trait(self.into()) + db.trait_items_index(self.module(db).id).get_parent_trait(self.id.into()).map(Trait::from) } pub fn container(self, db: &impl DefDatabase) -> Option { @@ -757,7 +749,7 @@ impl Const { } pub fn parent_trait(self, db: &impl DefDatabase) -> Option { - db.trait_items_index(self.module(db)).get_parent_trait(self.into()) + db.trait_items_index(self.module(db).id).get_parent_trait(self.id.into()).map(Trait::from) } pub fn container(self, db: &impl DefDatabase) -> Option { @@ -861,11 +853,11 @@ impl Trait { } pub fn name(self, db: &impl DefDatabase) -> Option { - self.trait_data(db).name().clone() + self.trait_data(db).name.clone() } pub fn items(self, db: &impl DefDatabase) -> Vec { - self.trait_data(db).items().to_vec() + self.trait_data(db).items.iter().map(|it| (*it).into()).collect() } fn direct_super_traits(self, db: &impl HirDatabase) -> Vec { @@ -912,10 +904,10 @@ impl Trait { pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option { let trait_data = self.trait_data(db); trait_data - .items() + .items .iter() .filter_map(|item| match item { - AssocItem::TypeAlias(t) => Some(*t), + AssocItemId::TypeAliasId(t) => Some(TypeAlias::from(*t)), _ => None, }) .find(|t| &t.name(db) == name) @@ -930,7 +922,7 @@ impl Trait { } pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc { - db.trait_data(self) + db.trait_data(self.id) } pub fn trait_ref(self, db: &impl HirDatabase) -> TraitRef { @@ -938,7 +930,7 @@ impl Trait { } pub fn is_auto(self, db: &impl DefDatabase) -> bool { - self.trait_data(db).is_auto() + self.trait_data(db).auto } pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver { @@ -971,7 +963,7 @@ impl TypeAlias { /// The containing trait, if this is a trait method definition. pub fn parent_trait(self, db: &impl DefDatabase) -> Option { - db.trait_items_index(self.module(db)).get_parent_trait(self.into()) + db.trait_items_index(self.module(db).id).get_parent_trait(self.id.into()).map(Trait::from) } pub fn container(self, db: &impl DefDatabase) -> Option { diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 0d35014a0f..73859e1e94 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -11,7 +11,6 @@ use crate::{ generics::{GenericDef, GenericParams}, ids, lang_item::{LangItemTarget, LangItems}, - traits::TraitData, ty::{ method_resolution::CrateImplBlocks, traits::{AssocTyValue, Impl}, @@ -26,7 +25,8 @@ use crate::{ pub use hir_def::db::{ BodyQuery, BodyWithSourceMapQuery, CrateDefMapQuery, DefDatabase2, DefDatabase2Storage, EnumDataQuery, ExprScopesQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage, - RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery, + RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery, TraitDataQuery, + TraitItemsIndexQuery, }; pub use hir_expand::db::{ AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, @@ -37,12 +37,6 @@ pub use hir_expand::db::{ #[salsa::query_group(DefDatabaseStorage)] #[salsa::requires(AstDatabase)] pub trait DefDatabase: HirDebugDatabase + DefDatabase2 { - #[salsa::invoke(crate::traits::TraitData::trait_data_query)] - fn trait_data(&self, t: Trait) -> Arc; - - #[salsa::invoke(crate::traits::TraitItemsIndex::trait_items_index)] - fn trait_items_index(&self, module: Module) -> crate::traits::TraitItemsIndex; - #[salsa::invoke(crate::generics::generic_params_query)] fn generic_params(&self, def: GenericDef) -> Arc; diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index da33c95915..7ac9a90414 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -33,7 +33,6 @@ pub mod source_binder; mod ids; mod adt; -mod traits; mod type_alias; mod ty; mod impl_block; diff --git a/crates/ra_hir/src/traits.rs b/crates/ra_hir/src/traits.rs deleted file mode 100644 index 858972c6fe..0000000000 --- a/crates/ra_hir/src/traits.rs +++ /dev/null @@ -1,82 +0,0 @@ -//! HIR for trait definitions. - -use std::sync::Arc; - -use hir_expand::name::AsName; - -use ra_syntax::ast::{self, NameOwner}; -use rustc_hash::FxHashMap; - -use crate::{ - db::{AstDatabase, DefDatabase}, - ids::LocationCtx, - AssocItem, Const, Function, HasSource, Module, Name, Trait, TypeAlias, -}; - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct TraitData { - name: Option, - items: Vec, - auto: bool, -} - -impl TraitData { - pub(crate) fn trait_data_query( - db: &(impl DefDatabase + AstDatabase), - tr: Trait, - ) -> Arc { - let src = tr.source(db); - let name = src.value.name().map(|n| n.as_name()); - let module = tr.module(db); - let ctx = LocationCtx::new(db, module.id, src.file_id); - let auto = src.value.is_auto(); - let items = if let Some(item_list) = src.value.item_list() { - item_list - .impl_items() - .map(|item_node| match item_node { - ast::ImplItem::FnDef(it) => Function { id: ctx.to_def(&it) }.into(), - ast::ImplItem::ConstDef(it) => Const { id: ctx.to_def(&it) }.into(), - ast::ImplItem::TypeAliasDef(it) => TypeAlias { id: ctx.to_def(&it) }.into(), - }) - .collect() - } else { - Vec::new() - }; - Arc::new(TraitData { name, items, auto }) - } - - pub(crate) fn name(&self) -> &Option { - &self.name - } - - pub(crate) fn items(&self) -> &[AssocItem] { - &self.items - } - - pub(crate) fn is_auto(&self) -> bool { - self.auto - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct TraitItemsIndex { - traits_by_def: FxHashMap, -} - -impl TraitItemsIndex { - pub(crate) fn trait_items_index(db: &impl DefDatabase, module: Module) -> TraitItemsIndex { - let mut index = TraitItemsIndex { traits_by_def: FxHashMap::default() }; - for decl in module.declarations(db) { - if let crate::ModuleDef::Trait(tr) = decl { - for item in tr.trait_data(db).items() { - index.traits_by_def.insert(*item, tr); - } - } - } - index - } - - pub(crate) fn get_parent_trait(&self, item: AssocItem) -> Option { - self.traits_by_def.get(&item).cloned() - } -} diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index d20aeaacf2..f377fca48a 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -232,8 +232,8 @@ fn iterate_trait_method_candidates( // trait, but if we find out it doesn't, we'll skip the rest of the // iteration let mut known_implemented = false; - for &item in data.items() { - if !is_valid_candidate(db, name, mode, item) { + for &item in data.items.iter() { + if !is_valid_candidate(db, name, mode, item.into()) { continue; } if !known_implemented { @@ -243,7 +243,7 @@ fn iterate_trait_method_candidates( } } known_implemented = true; - if let Some(result) = callback(&ty.value, item) { + if let Some(result) = callback(&ty.value, item.into()) { return Some(result); } } diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index 348aca07f1..fb4402463c 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs @@ -8,12 +8,13 @@ use ra_syntax::ast; use crate::{ adt::{EnumData, StructData}, body::{scope::ExprScopes, Body, BodySourceMap}, - imp::ImplData, + impls::ImplData, nameres::{ raw::{ImportSourceMap, RawItems}, CrateDefMap, }, - DefWithBodyId, EnumId, ImplId, ItemLoc, StructOrUnionId, + traits::{TraitData, TraitItemsIndex}, + DefWithBodyId, EnumId, ImplId, ItemLoc, ModuleId, StructOrUnionId, TraitId, }; #[salsa::query_group(InternDatabaseStorage)] @@ -59,6 +60,12 @@ pub trait DefDatabase2: InternDatabase + AstDatabase { #[salsa::invoke(ImplData::impl_data_query)] fn impl_data(&self, e: ImplId) -> Arc; + #[salsa::invoke(TraitData::trait_data_query)] + fn trait_data(&self, e: TraitId) -> Arc; + + #[salsa::invoke(TraitItemsIndex::trait_items_index)] + fn trait_items_index(&self, module: ModuleId) -> TraitItemsIndex; + #[salsa::invoke(Body::body_with_source_map_query)] fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc, Arc); diff --git a/crates/ra_hir_def/src/imp.rs b/crates/ra_hir_def/src/impls.rs similarity index 100% rename from crates/ra_hir_def/src/imp.rs rename to crates/ra_hir_def/src/impls.rs diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index dffc82ff8c..38c110570c 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -13,11 +13,12 @@ pub mod path; pub mod type_ref; pub mod builtin_type; pub mod adt; -pub mod imp; +pub mod impls; pub mod diagnostics; pub mod expr; pub mod body; pub mod generics; +pub mod traits; #[cfg(test)] mod test_db; diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index e5b073a0f8..c01e020ef1 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -165,6 +165,14 @@ impl ModuleScope { self.items.iter().chain(BUILTIN_SCOPE.iter()) } + pub fn declarations(&self) -> impl Iterator + '_ { + self.entries() + .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None }) + .flat_map(|per_ns| { + per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter()) + }) + } + /// Iterate over all module scoped macros pub fn macros<'a>(&'a self) -> impl Iterator + 'a { self.items diff --git a/crates/ra_hir_def/src/traits.rs b/crates/ra_hir_def/src/traits.rs new file mode 100644 index 0000000000..a8ba31594f --- /dev/null +++ b/crates/ra_hir_def/src/traits.rs @@ -0,0 +1,67 @@ +//! HIR for trait definitions. + +use std::sync::Arc; + +use hir_expand::name::{AsName, Name}; + +use ra_syntax::ast::{self, NameOwner}; +use rustc_hash::FxHashMap; + +use crate::{ + db::DefDatabase2, AssocItemId, AstItemDef, ConstId, FunctionId, LocationCtx, ModuleDefId, + ModuleId, TraitId, TypeAliasId, +}; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct TraitData { + pub name: Option, + pub items: Vec, + pub auto: bool, +} + +impl TraitData { + pub(crate) fn trait_data_query(db: &impl DefDatabase2, tr: TraitId) -> Arc { + let src = tr.source(db); + let name = src.value.name().map(|n| n.as_name()); + let module = tr.module(db); + let ctx = LocationCtx::new(db, module, src.file_id); + let auto = src.value.is_auto(); + let items = if let Some(item_list) = src.value.item_list() { + item_list + .impl_items() + .map(|item_node| match item_node { + ast::ImplItem::FnDef(it) => FunctionId::from_ast(ctx, &it).into(), + ast::ImplItem::ConstDef(it) => ConstId::from_ast(ctx, &it).into(), + ast::ImplItem::TypeAliasDef(it) => TypeAliasId::from_ast(ctx, &it).into(), + }) + .collect() + } else { + Vec::new() + }; + Arc::new(TraitData { name, items, auto }) + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct TraitItemsIndex { + traits_by_def: FxHashMap, +} + +impl TraitItemsIndex { + pub fn trait_items_index(db: &impl DefDatabase2, module: ModuleId) -> TraitItemsIndex { + let mut index = TraitItemsIndex { traits_by_def: FxHashMap::default() }; + let crate_def_map = db.crate_def_map(module.krate); + for decl in crate_def_map[module.module_id].scope.declarations() { + if let ModuleDefId::TraitId(tr) = decl { + for item in db.trait_data(tr).items.iter() { + index.traits_by_def.insert(*item, tr); + } + } + } + index + } + + pub fn get_parent_trait(&self, item: AssocItemId) -> Option { + self.traits_by_def.get(&item).cloned() + } +} From cebeedc66fc40097eae20bf1767a285d00269966 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 16:03:59 +0300 Subject: [PATCH 10/24] Next gen IDs for functions The current system with AstIds has two primaraly drawbacks: * It is possible to manufacture IDs out of thin air. For example, it's possible to create IDs for items which are not considered in CrateDefMap due to cfg. Or it is possible to mixup structs and unions, because they share ID space. * Getting the ID of a parent requires a secondary index. Instead, the plan is to pursue the more traditional approach, where each items stores the id of the parent declaration. This makes `FromSource` more awkward, but also more correct: now, to get from an AST to HIR, we first do this recursively for the parent item, and the just search the children of the parent for the matching def --- crates/ra_hir/src/code_model.rs | 25 ++++---- crates/ra_hir/src/code_model/src.rs | 3 +- crates/ra_hir/src/from_source.rs | 65 ++++++++++++++++++--- crates/ra_hir/src/source_binder.rs | 2 +- crates/ra_hir_def/src/body.rs | 3 +- crates/ra_hir_def/src/db.rs | 4 +- crates/ra_hir_def/src/generics.rs | 4 +- crates/ra_hir_def/src/impls.rs | 12 +++- crates/ra_hir_def/src/lib.rs | 66 ++++++++++++++++++++-- crates/ra_hir_def/src/nameres/collector.rs | 13 +++-- crates/ra_hir_def/src/traits.rs | 25 ++++++-- crates/ra_syntax/src/ptr.rs | 10 +++- 12 files changed, 190 insertions(+), 42 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index f436d5d5e5..c49190a0f0 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -12,7 +12,8 @@ use hir_def::{ builtin_type::BuiltinType, traits::TraitData, type_ref::{Mutability, TypeRef}, - AssocItemId, CrateModuleId, ImplId, LocalEnumVariantId, LocalStructFieldId, ModuleId, UnionId, + AssocItemId, CrateModuleId, FunctionContainerId, HasModule, ImplId, LocalEnumVariantId, + LocalStructFieldId, Lookup, ModuleId, UnionId, }; use hir_expand::{ diagnostics::DiagnosticSink, @@ -647,7 +648,7 @@ impl FnData { impl Function { pub fn module(self, db: &impl DefDatabase) -> Module { - Module { id: self.id.module(db) } + self.id.lookup(db).module(db).into() } pub fn krate(self, db: &impl DefDatabase) -> Option { @@ -680,21 +681,25 @@ impl Function { /// The containing impl block, if this is a method. pub fn impl_block(self, db: &impl DefDatabase) -> Option { - ImplBlock::containing(db, self.into()) + match self.container(db) { + Some(Container::ImplBlock(it)) => Some(it), + _ => None, + } } /// The containing trait, if this is a trait method definition. pub fn parent_trait(self, db: &impl DefDatabase) -> Option { - db.trait_items_index(self.module(db).id).get_parent_trait(self.id.into()).map(Trait::from) + match self.container(db) { + Some(Container::Trait(it)) => Some(it), + _ => None, + } } pub fn container(self, db: &impl DefDatabase) -> Option { - if let Some(impl_block) = self.impl_block(db) { - Some(impl_block.into()) - } else if let Some(trait_) = self.parent_trait(db) { - Some(trait_.into()) - } else { - None + match self.id.lookup(db).container { + FunctionContainerId::TraitId(it) => Some(Container::Trait(it.into())), + FunctionContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())), + FunctionContainerId::ModuleId(_) => None, } } diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs index 556417b0f2..91cab7414f 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/code_model/src.rs @@ -1,5 +1,6 @@ //! FIXME: write short doc here +use hir_def::{HasSource as _, Lookup}; use ra_syntax::ast::{self, AstNode}; use crate::{ @@ -113,7 +114,7 @@ impl HasSource for EnumVariant { impl HasSource for Function { type Ast = ast::FnDef; fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source { - self.id.source(db) + self.id.lookup(db).source(db) } } impl HasSource for Const { diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index f4dca25cb6..303d5f1389 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -4,15 +4,15 @@ use hir_def::{ModuleId, StructId, StructOrUnionId, UnionId}; use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; use ra_syntax::{ ast::{self, AstNode, NameOwner}, - match_ast, + match_ast, AstPtr, }; use crate::{ db::{AstDatabase, DefDatabase, HirDatabase}, ids::{AstItemDef, LocationCtx}, - Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasBody, HasSource, ImplBlock, - Local, MacroDef, Module, ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, - Union, VariantDef, + AssocItem, Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasBody, HasSource, + ImplBlock, Local, MacroDef, Module, ModuleDef, ModuleSource, Source, Static, Struct, + StructField, Trait, TypeAlias, Union, VariantDef, }; pub trait FromSource: Sized { @@ -52,10 +52,51 @@ impl FromSource for Trait { impl FromSource for Function { type Ast = ast::FnDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { - let id = from_source(db, src)?; - Some(Function { id }) + // FIXME: this doesn't try to handle nested declarations + for container in src.value.syntax().ancestors() { + let res = match_ast! { + match container { + ast::TraitDef(it) => { + let c = Trait::from_source(db, src.with_value(it))?; + c.items(db) + .into_iter() + .filter_map(|it| match it { + AssocItem::Function(it) => Some(it), + _ => None + }) + .find(|it| same_source(&it.source(db), &src))? + }, + ast::ImplBlock(it) => { + let c = ImplBlock::from_source(db, src.with_value(it))?; + c.items(db) + .into_iter() + .filter_map(|it| match it { + AssocItem::Function(it) => Some(it), + _ => None + }) + .find(|it| same_source(&it.source(db), &src))? + + }, + _ => { continue }, + } + }; + return Some(res); + } + + let module_source = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); + let c = Module::from_definition(db, src.with_value(module_source))?; + let res = c + .declarations(db) + .into_iter() + .filter_map(|it| match it { + ModuleDef::Function(it) => Some(it), + _ => None, + }) + .find(|it| same_source(&it.source(db), &src)); + res } } + impl FromSource for Const { type Ast = ast::ConstDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { @@ -108,7 +149,7 @@ impl FromSource for EnumVariant { let parent_enum = src.value.parent_enum(); let src_enum = Source { file_id: src.file_id, value: parent_enum }; let variants = Enum::from_source(db, src_enum)?.variants(db); - variants.into_iter().find(|v| v.source(db) == src) + variants.into_iter().find(|v| same_source(&v.source(db), &src)) } } @@ -216,3 +257,13 @@ where let ctx = LocationCtx::new(db, module.id, src.file_id); Some(DEF::from_ast(ctx, &src.value)) } + +/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are +/// equal if they point to exactly the same object. +/// +/// In general, we do not guarantee that we have exactly one instance of a +/// syntax tree for each file. We probably should add such guanratree, but, for +/// the time being, we will use identity-less AstPtr comparison. +fn same_source(s1: &Source, s2: &Source) -> bool { + s1.as_ref().map(AstPtr::new) == s2.as_ref().map(AstPtr::new) +} diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index a1c1daacdb..5d9e22ee2e 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -70,7 +70,7 @@ fn def_with_body_from_child_node( child.value.ancestors().find_map(|node| { match_ast! { match node { - ast::FnDef(def) => { Some(Function {id: ctx.to_def(&def) }.into()) }, + ast::FnDef(def) => { return Function::from_source(db, child.with_value(def)).map(DefWithBody::from); }, ast::ConstDef(def) => { Some(Const { id: ctx.to_def(&def) }.into()) }, ast::StaticDef(def) => { Some(Static { id: ctx.to_def(&def) }.into()) }, _ => { None }, diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 3804b65c7e..b69d4dea65 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -17,7 +17,7 @@ use crate::{ expr::{Expr, ExprId, Pat, PatId}, nameres::CrateDefMap, path::Path, - AstItemDef, DefWithBodyId, ModuleId, + AstItemDef, DefWithBodyId, HasModule, HasSource, Lookup, ModuleId, }; pub struct Expander { @@ -149,6 +149,7 @@ impl Body { let (file_id, module, body) = match def { DefWithBodyId::FunctionId(f) => { + let f = f.lookup(db); let src = f.source(db); params = src.value.param_list(); (src.file_id, f.module(db), src.value.body().map(ast::Expr::from)) diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index fb4402463c..e4ffdebe97 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs @@ -14,13 +14,13 @@ use crate::{ CrateDefMap, }, traits::{TraitData, TraitItemsIndex}, - DefWithBodyId, EnumId, ImplId, ItemLoc, ModuleId, StructOrUnionId, TraitId, + DefWithBodyId, EnumId, FunctionLoc, ImplId, ItemLoc, ModuleId, StructOrUnionId, TraitId, }; #[salsa::query_group(InternDatabaseStorage)] pub trait InternDatabase: SourceDatabase { #[salsa::interned] - fn intern_function(&self, loc: ItemLoc) -> crate::FunctionId; + fn intern_function(&self, loc: FunctionLoc) -> crate::FunctionId; #[salsa::interned] fn intern_struct_or_union(&self, loc: ItemLoc) -> crate::StructOrUnionId; #[salsa::interned] diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index 4adfc16bbb..11dd2a9487 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs @@ -11,7 +11,7 @@ use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; use crate::{ db::DefDatabase2, type_ref::{TypeBound, TypeRef}, - AdtId, AstItemDef, GenericDefId, + AdtId, AstItemDef, GenericDefId, HasSource, Lookup, }; /// Data about a generic parameter (to a function, struct, impl, ...). @@ -53,7 +53,7 @@ impl GenericParams { let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; // FIXME: add `: Sized` bound for everything except for `Self` in traits match def { - GenericDefId::FunctionId(it) => generics.fill(&it.source(db).value, start), + GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value, start), GenericDefId::AdtId(AdtId::StructId(it)) => { generics.fill(&it.0.source(db).value, start) } diff --git a/crates/ra_hir_def/src/impls.rs b/crates/ra_hir_def/src/impls.rs index 4323dfcb69..9be38c5e18 100644 --- a/crates/ra_hir_def/src/impls.rs +++ b/crates/ra_hir_def/src/impls.rs @@ -5,11 +5,12 @@ use std::sync::Arc; +use hir_expand::AstId; use ra_syntax::ast; use crate::{ - db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstId, FunctionId, ImplId, - LocationCtx, TypeAliasId, + db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstId, FunctionContainerId, + FunctionLoc, ImplId, Intern, LocationCtx, TypeAliasId, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -35,7 +36,12 @@ impl ImplData { .impl_items() .map(|item_node| match item_node { ast::ImplItem::FnDef(it) => { - FunctionId::from_ast_id(ctx, items.ast_id(&it)).into() + let func_id = FunctionLoc { + container: FunctionContainerId::ImplId(id), + ast_id: AstId::new(src.file_id, items.ast_id(&it)), + } + .intern(db); + func_id.into() } ast::ImplItem::ConstDef(it) => { ConstId::from_ast_id(ctx, items.ast_id(&it)).into() diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 38c110570c..b9a13776ff 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -199,15 +199,33 @@ pub trait AstItemDef: salsa::InternKey + Clone { pub struct FunctionId(salsa::InternId); impl_intern_key!(FunctionId); -impl AstItemDef for FunctionId { - fn intern(db: &impl InternDatabase, loc: ItemLoc) -> Self { - db.intern_function(loc) +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct FunctionLoc { + pub container: FunctionContainerId, + pub ast_id: AstId, +} + +impl Intern for FunctionLoc { + type ID = FunctionId; + fn intern(self, db: &impl db::DefDatabase2) -> FunctionId { + db.intern_function(self) } - fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc { - db.lookup_intern_function(self) +} + +impl Lookup for FunctionId { + type Data = FunctionLoc; + fn lookup(&self, db: &impl db::DefDatabase2) -> FunctionLoc { + db.lookup_intern_function(*self) } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum FunctionContainerId { + ModuleId(ModuleId), + ImplId(ImplId), + TraitId(TraitId), +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct StructOrUnionId(salsa::InternId); impl_intern_key!(StructOrUnionId); @@ -433,3 +451,41 @@ impl_froms!( EnumVariantId, ConstId ); + +trait Intern { + type ID; + fn intern(self, db: &impl db::DefDatabase2) -> Self::ID; +} + +pub trait Lookup { + type Data; + fn lookup(&self, db: &impl db::DefDatabase2) -> Self::Data; +} + +pub trait HasModule { + fn module(&self, db: &impl db::DefDatabase2) -> ModuleId; +} + +impl HasModule for FunctionLoc { + fn module(&self, db: &impl db::DefDatabase2) -> ModuleId { + match self.container { + FunctionContainerId::ModuleId(it) => it, + FunctionContainerId::ImplId(it) => it.module(db), + FunctionContainerId::TraitId(it) => it.module(db), + } + } +} + +pub trait HasSource { + type Value; + fn source(&self, db: &impl db::DefDatabase2) -> Source; +} + +impl HasSource for FunctionLoc { + type Value = ast::FnDef; + + fn source(&self, db: &impl db::DefDatabase2) -> Source { + let node = self.ast_id.to_node(db); + Source::new(self.ast_id.file_id(), node) + } +} diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 8f426b0977..d2ed94a876 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -19,9 +19,9 @@ use crate::{ per_ns::PerNs, raw, CrateDefMap, ModuleData, Resolution, ResolveMode, }, path::{Path, PathKind}, - AdtId, AstId, AstItemDef, ConstId, CrateModuleId, EnumId, EnumVariantId, FunctionId, ImplId, - LocationCtx, ModuleDefId, ModuleId, StaticId, StructId, StructOrUnionId, TraitId, TypeAliasId, - UnionId, + AdtId, AstId, AstItemDef, ConstId, CrateModuleId, EnumId, EnumVariantId, FunctionContainerId, + FunctionLoc, ImplId, Intern, LocationCtx, ModuleDefId, ModuleId, StaticId, StructId, + StructOrUnionId, TraitId, TypeAliasId, UnionId, }; pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) -> CrateDefMap { @@ -673,7 +673,12 @@ where let name = def.name.clone(); let def: PerNs = match def.kind { raw::DefKind::Function(ast_id) => { - let f = FunctionId::from_ast_id(ctx, ast_id); + let f = FunctionLoc { + container: FunctionContainerId::ModuleId(module), + ast_id: AstId::new(self.file_id, ast_id), + } + .intern(self.def_collector.db); + PerNs::values(f.into()) } raw::DefKind::Struct(ast_id) => { diff --git a/crates/ra_hir_def/src/traits.rs b/crates/ra_hir_def/src/traits.rs index a8ba31594f..6e36bc0d0c 100644 --- a/crates/ra_hir_def/src/traits.rs +++ b/crates/ra_hir_def/src/traits.rs @@ -2,14 +2,17 @@ use std::sync::Arc; -use hir_expand::name::{AsName, Name}; +use hir_expand::{ + name::{AsName, Name}, + AstId, +}; use ra_syntax::ast::{self, NameOwner}; use rustc_hash::FxHashMap; use crate::{ - db::DefDatabase2, AssocItemId, AstItemDef, ConstId, FunctionId, LocationCtx, ModuleDefId, - ModuleId, TraitId, TypeAliasId, + db::DefDatabase2, AssocItemId, AstItemDef, ConstId, FunctionContainerId, FunctionLoc, Intern, + LocationCtx, ModuleDefId, ModuleId, TraitId, TypeAliasId, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -26,11 +29,17 @@ impl TraitData { let module = tr.module(db); let ctx = LocationCtx::new(db, module, src.file_id); let auto = src.value.is_auto(); + let ast_id_map = db.ast_id_map(src.file_id); let items = if let Some(item_list) = src.value.item_list() { item_list .impl_items() .map(|item_node| match item_node { - ast::ImplItem::FnDef(it) => FunctionId::from_ast(ctx, &it).into(), + ast::ImplItem::FnDef(it) => FunctionLoc { + container: FunctionContainerId::TraitId(tr), + ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), + } + .intern(db) + .into(), ast::ImplItem::ConstDef(it) => ConstId::from_ast(ctx, &it).into(), ast::ImplItem::TypeAliasDef(it) => TypeAliasId::from_ast(ctx, &it).into(), }) @@ -54,7 +63,13 @@ impl TraitItemsIndex { for decl in crate_def_map[module.module_id].scope.declarations() { if let ModuleDefId::TraitId(tr) = decl { for item in db.trait_data(tr).items.iter() { - index.traits_by_def.insert(*item, tr); + match item { + AssocItemId::FunctionId(_) => (), + _ => { + let prev = index.traits_by_def.insert(*item, tr); + assert!(prev.is_none()); + } + } } } } diff --git a/crates/ra_syntax/src/ptr.rs b/crates/ra_syntax/src/ptr.rs index 31167cada0..e049fce611 100644 --- a/crates/ra_syntax/src/ptr.rs +++ b/crates/ra_syntax/src/ptr.rs @@ -43,7 +43,7 @@ impl SyntaxNodePtr { } /// Like `SyntaxNodePtr`, but remembers the type of node -#[derive(Debug, PartialEq, Eq, Hash)] +#[derive(Debug, Hash)] pub struct AstPtr { raw: SyntaxNodePtr, _ty: PhantomData N>, @@ -56,6 +56,14 @@ impl Clone for AstPtr { } } +impl Eq for AstPtr {} + +impl PartialEq for AstPtr { + fn eq(&self, other: &AstPtr) -> bool { + self.raw == other.raw + } +} + impl AstPtr { pub fn new(node: &N) -> AstPtr { AstPtr { raw: SyntaxNodePtr::new(node.syntax()), _ty: PhantomData } From 0a9c80053ffcd72d076ca3792bf4a9ddb94eaf95 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Wed, 20 Nov 2019 12:21:31 +0800 Subject: [PATCH 11/24] Fix expand macro --- crates/ra_hir/src/source_binder.rs | 13 ++++++++++--- crates/ra_ide_api/src/expand.rs | 2 +- crates/ra_ide_api/src/expand_macro.rs | 10 +++++----- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 5d9e22ee2e..caa8d0082f 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -405,9 +405,16 @@ impl SourceAnalyzer { implements_trait(&canonical_ty, db, &self.resolver, krate, std_future_trait) } - pub fn expand(&self, db: &impl HirDatabase, macro_call: &ast::MacroCall) -> Option { - let def = self.resolve_macro_call(db, macro_call)?.id; - let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(macro_call)); + pub fn expand( + &self, + db: &impl HirDatabase, + macro_call: Source<&ast::MacroCall>, + ) -> Option { + let def = self.resolve_macro_call(db, macro_call.value)?.id; + let ast_id = AstId::new( + macro_call.file_id, + db.ast_id_map(macro_call.file_id).ast_id(macro_call.value), + ); let macro_call_loc = MacroCallLoc { def, ast_id }; Some(Expansion { macro_call_id: db.intern_macro(macro_call_loc) }) } diff --git a/crates/ra_ide_api/src/expand.rs b/crates/ra_ide_api/src/expand.rs index 0ad125a9e3..2f1abf509a 100644 --- a/crates/ra_ide_api/src/expand.rs +++ b/crates/ra_ide_api/src/expand.rs @@ -55,7 +55,7 @@ pub(crate) fn descend_into_macros( } let source_analyzer = hir::SourceAnalyzer::new(db, token.with_value(token.value.parent()).as_ref(), None); - let exp = source_analyzer.expand(db, ¯o_call)?; + let exp = source_analyzer.expand(db, token.with_value(¯o_call))?; exp.map_token_down(db, token.as_ref()) }) .last() diff --git a/crates/ra_ide_api/src/expand_macro.rs b/crates/ra_ide_api/src/expand_macro.rs index 2d478ec09b..7f39262dc9 100644 --- a/crates/ra_ide_api/src/expand_macro.rs +++ b/crates/ra_ide_api/src/expand_macro.rs @@ -23,7 +23,7 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option< let mac = name_ref.syntax().ancestors().find_map(ast::MacroCall::cast)?; let source = hir::Source::new(position.file_id.into(), mac.syntax()); - let expanded = expand_macro_recur(db, source, &mac)?; + let expanded = expand_macro_recur(db, source, source.with_value(&mac))?; // FIXME: // macro expansion may lose all white space information @@ -35,10 +35,10 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option< fn expand_macro_recur( db: &RootDatabase, source: hir::Source<&SyntaxNode>, - macro_call: &ast::MacroCall, + macro_call: hir::Source<&ast::MacroCall>, ) -> Option { let analyzer = hir::SourceAnalyzer::new(db, source, None); - let expansion = analyzer.expand(db, ¯o_call)?; + let expansion = analyzer.expand(db, macro_call)?; let macro_file_id = expansion.file_id(); let expanded: SyntaxNode = db.parse_or_expand(macro_file_id)?; @@ -46,8 +46,8 @@ fn expand_macro_recur( let mut replaces = FxHashMap::default(); for child in children.into_iter() { - let source = hir::Source::new(macro_file_id, source.value); - let new_node = expand_macro_recur(db, source, &child)?; + let node = hir::Source::new(macro_file_id, &child); + let new_node = expand_macro_recur(db, source, node)?; replaces.insert(child.syntax().clone().into(), new_node.into()); } From 3888487ca8af25047351542dbf37b90e0029e230 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 16:25:00 +0300 Subject: [PATCH 12/24] Remove duplicate tests --- crates/ra_ide_api/src/references/rename.rs | 132 --------------------- 1 file changed, 132 deletions(-) diff --git a/crates/ra_ide_api/src/references/rename.rs b/crates/ra_ide_api/src/references/rename.rs index 4ea372e6f0..d58496049e 100644 --- a/crates/ra_ide_api/src/references/rename.rs +++ b/crates/ra_ide_api/src/references/rename.rs @@ -121,140 +121,8 @@ mod tests { use crate::{ mock_analysis::analysis_and_position, mock_analysis::single_file_with_position, FileId, - ReferenceSearchResult, }; - #[test] - fn test_find_all_refs_for_local() { - let code = r#" - fn main() { - let mut i = 1; - let j = 1; - i = i<|> + j; - - { - i = 0; - } - - i = 5; - }"#; - - let refs = get_all_refs(code); - assert_eq!(refs.len(), 5); - } - - #[test] - fn test_find_all_refs_for_param_inside() { - let code = r#" - fn foo(i : u32) -> u32 { - i<|> - }"#; - - let refs = get_all_refs(code); - assert_eq!(refs.len(), 2); - } - - #[test] - fn test_find_all_refs_for_fn_param() { - let code = r#" - fn foo(i<|> : u32) -> u32 { - i - }"#; - - let refs = get_all_refs(code); - assert_eq!(refs.len(), 2); - } - - #[test] - fn test_find_all_refs_field_name() { - let code = r#" - //- /lib.rs - struct Foo { - pub spam<|>: u32, - } - - fn main(s: Foo) { - let f = s.spam; - } - "#; - - let refs = get_all_refs(code); - assert_eq!(refs.len(), 2); - } - - #[test] - fn test_find_all_refs_impl_item_name() { - let code = r#" - //- /lib.rs - struct Foo; - impl Foo { - fn f<|>(&self) { } - } - "#; - - let refs = get_all_refs(code); - assert_eq!(refs.len(), 1); - } - - #[test] - fn test_find_all_refs_enum_var_name() { - let code = r#" - //- /lib.rs - enum Foo { - A, - B<|>, - C, - } - "#; - - let refs = get_all_refs(code); - assert_eq!(refs.len(), 1); - } - - #[test] - fn test_find_all_refs_modules() { - let code = r#" - //- /lib.rs - pub mod foo; - pub mod bar; - - fn f() { - let i = foo::Foo { n: 5 }; - } - - //- /foo.rs - use crate::bar; - - pub struct Foo { - pub n: u32, - } - - fn f() { - let i = bar::Bar { n: 5 }; - } - - //- /bar.rs - use crate::foo; - - pub struct Bar { - pub n: u32, - } - - fn f() { - let i = foo::Foo<|> { n: 5 }; - } - "#; - - let (analysis, pos) = analysis_and_position(code); - let refs = analysis.find_all_refs(pos, None).unwrap().unwrap(); - assert_eq!(refs.len(), 3); - } - - fn get_all_refs(text: &str) -> ReferenceSearchResult { - let (analysis, position) = single_file_with_position(text); - analysis.find_all_refs(position, None).unwrap().unwrap() - } - #[test] fn test_rename_for_local() { test_rename( From 64c21ed19594b323e72605ba8c5dd4c6eee433f6 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 17:39:58 +0300 Subject: [PATCH 13/24] Switch type aliases to new sources --- crates/ra_hir/src/code_model.rs | 28 +++--- crates/ra_hir/src/code_model/src.rs | 2 +- crates/ra_hir/src/from_source.rs | 112 +++++++++++++-------- crates/ra_hir_def/src/db.rs | 6 +- crates/ra_hir_def/src/generics.rs | 2 +- crates/ra_hir_def/src/impls.rs | 13 ++- crates/ra_hir_def/src/lib.rs | 48 ++++++++- crates/ra_hir_def/src/nameres/collector.rs | 14 ++- crates/ra_hir_def/src/traits.rs | 10 +- 9 files changed, 162 insertions(+), 73 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index c49190a0f0..b8d48a500c 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -13,7 +13,7 @@ use hir_def::{ traits::TraitData, type_ref::{Mutability, TypeRef}, AssocItemId, CrateModuleId, FunctionContainerId, HasModule, ImplId, LocalEnumVariantId, - LocalStructFieldId, Lookup, ModuleId, UnionId, + LocalStructFieldId, Lookup, ModuleId, TypeAliasContainerId, UnionId, }; use hir_expand::{ diagnostics::DiagnosticSink, @@ -954,30 +954,34 @@ pub struct TypeAlias { impl TypeAlias { pub fn module(self, db: &impl DefDatabase) -> Module { - Module { id: self.id.module(db) } + Module { id: self.id.lookup(db).module(db) } } pub fn krate(self, db: &impl DefDatabase) -> Option { Some(self.module(db).krate()) } - /// The containing impl block, if this is a method. + /// The containing impl block, if this is a type alias. pub fn impl_block(self, db: &impl DefDatabase) -> Option { - ImplBlock::containing(db, self.into()) + match self.container(db) { + Some(Container::ImplBlock(it)) => Some(it), + _ => None, + } } - /// The containing trait, if this is a trait method definition. + /// The containing trait, if this is a trait type alias definition. pub fn parent_trait(self, db: &impl DefDatabase) -> Option { - db.trait_items_index(self.module(db).id).get_parent_trait(self.id.into()).map(Trait::from) + match self.container(db) { + Some(Container::Trait(it)) => Some(it), + _ => None, + } } pub fn container(self, db: &impl DefDatabase) -> Option { - if let Some(impl_block) = self.impl_block(db) { - Some(impl_block.into()) - } else if let Some(trait_) = self.parent_trait(db) { - Some(trait_.into()) - } else { - None + match self.id.lookup(db).container { + TypeAliasContainerId::TraitId(it) => Some(Container::Trait(it.into())), + TypeAliasContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())), + TypeAliasContainerId::ModuleId(_) => None, } } diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs index 91cab7414f..04675e08ef 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/code_model/src.rs @@ -138,7 +138,7 @@ impl HasSource for Trait { impl HasSource for TypeAlias { type Ast = ast::TypeAliasDef; fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source { - self.id.source(db) + self.id.lookup(db).source(db) } } impl HasSource for MacroDef { diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 303d5f1389..f5fdaafa37 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -4,7 +4,7 @@ use hir_def::{ModuleId, StructId, StructOrUnionId, UnionId}; use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; use ra_syntax::{ ast::{self, AstNode, NameOwner}, - match_ast, AstPtr, + match_ast, AstPtr, SyntaxNode, }; use crate::{ @@ -52,48 +52,27 @@ impl FromSource for Trait { impl FromSource for Function { type Ast = ast::FnDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { - // FIXME: this doesn't try to handle nested declarations - for container in src.value.syntax().ancestors() { - let res = match_ast! { - match container { - ast::TraitDef(it) => { - let c = Trait::from_source(db, src.with_value(it))?; - c.items(db) - .into_iter() - .filter_map(|it| match it { - AssocItem::Function(it) => Some(it), - _ => None - }) - .find(|it| same_source(&it.source(db), &src))? - }, - ast::ImplBlock(it) => { - let c = ImplBlock::from_source(db, src.with_value(it))?; - c.items(db) - .into_iter() - .filter_map(|it| match it { - AssocItem::Function(it) => Some(it), - _ => None - }) - .find(|it| same_source(&it.source(db), &src))? - - }, - _ => { continue }, - } - }; - return Some(res); - } - - let module_source = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); - let c = Module::from_definition(db, src.with_value(module_source))?; - let res = c - .declarations(db) + let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? { + Container::Trait(it) => it.items(db), + Container::ImplBlock(it) => it.items(db), + Container::Module(m) => { + return m + .declarations(db) + .into_iter() + .filter_map(|it| match it { + ModuleDef::Function(it) => Some(it), + _ => None, + }) + .find(|it| same_source(&it.source(db), &src)) + } + }; + items .into_iter() .filter_map(|it| match it { - ModuleDef::Function(it) => Some(it), + AssocItem::Function(it) => Some(it), _ => None, }) - .find(|it| same_source(&it.source(db), &src)); - res + .find(|it| same_source(&it.source(db), &src)) } } @@ -114,8 +93,27 @@ impl FromSource for Static { impl FromSource for TypeAlias { type Ast = ast::TypeAliasDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { - let id = from_source(db, src)?; - Some(TypeAlias { id }) + let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? { + Container::Trait(it) => it.items(db), + Container::ImplBlock(it) => it.items(db), + Container::Module(m) => { + return m + .declarations(db) + .into_iter() + .filter_map(|it| match it { + ModuleDef::TypeAlias(it) => Some(it), + _ => None, + }) + .find(|it| same_source(&it.source(db), &src)) + } + }; + items + .into_iter() + .filter_map(|it| match it { + AssocItem::TypeAlias(it) => Some(it), + _ => None, + }) + .find(|it| same_source(&it.source(db), &src)) } } @@ -258,6 +256,38 @@ where Some(DEF::from_ast(ctx, &src.value)) } +enum Container { + Trait(Trait), + ImplBlock(ImplBlock), + Module(Module), +} + +impl Container { + fn find(db: &impl DefDatabase, src: Source<&SyntaxNode>) -> Option { + // FIXME: this doesn't try to handle nested declarations + for container in src.value.ancestors() { + let res = match_ast! { + match container { + ast::TraitDef(it) => { + let c = Trait::from_source(db, src.with_value(it))?; + Container::Trait(c) + }, + ast::ImplBlock(it) => { + let c = ImplBlock::from_source(db, src.with_value(it))?; + Container::ImplBlock(c) + }, + _ => { continue }, + } + }; + return Some(res); + } + + let module_source = ModuleSource::from_child_node(db, src); + let c = Module::from_definition(db, src.with_value(module_source))?; + Some(Container::Module(c)) + } +} + /// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are /// equal if they point to exactly the same object. /// diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index e4ffdebe97..d6d32fb8c1 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs @@ -14,13 +14,13 @@ use crate::{ CrateDefMap, }, traits::{TraitData, TraitItemsIndex}, - DefWithBodyId, EnumId, FunctionLoc, ImplId, ItemLoc, ModuleId, StructOrUnionId, TraitId, + DefWithBodyId, EnumId, ImplId, ItemLoc, ModuleId, StructOrUnionId, TraitId, }; #[salsa::query_group(InternDatabaseStorage)] pub trait InternDatabase: SourceDatabase { #[salsa::interned] - fn intern_function(&self, loc: FunctionLoc) -> crate::FunctionId; + fn intern_function(&self, loc: crate::FunctionLoc) -> crate::FunctionId; #[salsa::interned] fn intern_struct_or_union(&self, loc: ItemLoc) -> crate::StructOrUnionId; #[salsa::interned] @@ -32,7 +32,7 @@ pub trait InternDatabase: SourceDatabase { #[salsa::interned] fn intern_trait(&self, loc: ItemLoc) -> crate::TraitId; #[salsa::interned] - fn intern_type_alias(&self, loc: ItemLoc) -> crate::TypeAliasId; + fn intern_type_alias(&self, loc: crate::TypeAliasLoc) -> crate::TypeAliasId; #[salsa::interned] fn intern_impl(&self, loc: ItemLoc) -> crate::ImplId; } diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index 11dd2a9487..17a5d5f436 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs @@ -72,7 +72,7 @@ impl GenericParams { let self_param = TypeRef::Path(name::SELF_TYPE.into()); generics.fill_bounds(&it.source(db).value, self_param); } - GenericDefId::TypeAliasId(it) => generics.fill(&it.source(db).value, start), + GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value, start), // Note that we don't add `Self` here: in `impl`s, `Self` is not a // type-parameter, but rather is a type-alias for impl's target // type, so this is handled by the resolver. diff --git a/crates/ra_hir_def/src/impls.rs b/crates/ra_hir_def/src/impls.rs index 9be38c5e18..703e4d503b 100644 --- a/crates/ra_hir_def/src/impls.rs +++ b/crates/ra_hir_def/src/impls.rs @@ -10,7 +10,7 @@ use ra_syntax::ast; use crate::{ db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstId, FunctionContainerId, - FunctionLoc, ImplId, Intern, LocationCtx, TypeAliasId, + FunctionLoc, ImplId, Intern, LocationCtx, TypeAliasContainerId, TypeAliasLoc, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -36,18 +36,23 @@ impl ImplData { .impl_items() .map(|item_node| match item_node { ast::ImplItem::FnDef(it) => { - let func_id = FunctionLoc { + let def = FunctionLoc { container: FunctionContainerId::ImplId(id), ast_id: AstId::new(src.file_id, items.ast_id(&it)), } .intern(db); - func_id.into() + def.into() } ast::ImplItem::ConstDef(it) => { ConstId::from_ast_id(ctx, items.ast_id(&it)).into() } ast::ImplItem::TypeAliasDef(it) => { - TypeAliasId::from_ast_id(ctx, items.ast_id(&it)).into() + let def = TypeAliasLoc { + container: TypeAliasContainerId::ImplId(id), + ast_id: AstId::new(src.file_id, items.ast_id(&it)), + } + .intern(db); + def.into() } }) .collect() diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index b9a13776ff..6052370b4d 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -332,15 +332,34 @@ impl AstItemDef for TraitId { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TypeAliasId(salsa::InternId); impl_intern_key!(TypeAliasId); -impl AstItemDef for TypeAliasId { - fn intern(db: &impl InternDatabase, loc: ItemLoc) -> Self { - db.intern_type_alias(loc) + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TypeAliasLoc { + pub container: TypeAliasContainerId, + pub ast_id: AstId, +} + +impl Intern for TypeAliasLoc { + type ID = TypeAliasId; + fn intern(self, db: &impl db::DefDatabase2) -> TypeAliasId { + db.intern_type_alias(self) } - fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc { - db.lookup_intern_type_alias(self) +} + +impl Lookup for TypeAliasId { + type Data = TypeAliasLoc; + fn lookup(&self, db: &impl db::DefDatabase2) -> TypeAliasLoc { + db.lookup_intern_type_alias(*self) } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum TypeAliasContainerId { + ModuleId(ModuleId), + ImplId(ImplId), + TraitId(TraitId), +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ImplId(salsa::InternId); impl_intern_key!(ImplId); @@ -476,6 +495,16 @@ impl HasModule for FunctionLoc { } } +impl HasModule for TypeAliasLoc { + fn module(&self, db: &impl db::DefDatabase2) -> ModuleId { + match self.container { + TypeAliasContainerId::ModuleId(it) => it, + TypeAliasContainerId::ImplId(it) => it.module(db), + TypeAliasContainerId::TraitId(it) => it.module(db), + } + } +} + pub trait HasSource { type Value; fn source(&self, db: &impl db::DefDatabase2) -> Source; @@ -489,3 +518,12 @@ impl HasSource for FunctionLoc { Source::new(self.ast_id.file_id(), node) } } + +impl HasSource for TypeAliasLoc { + type Value = ast::TypeAliasDef; + + fn source(&self, db: &impl db::DefDatabase2) -> Source { + let node = self.ast_id.to_node(db); + Source::new(self.ast_id.file_id(), node) + } +} diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index d2ed94a876..060185b619 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -21,7 +21,7 @@ use crate::{ path::{Path, PathKind}, AdtId, AstId, AstItemDef, ConstId, CrateModuleId, EnumId, EnumVariantId, FunctionContainerId, FunctionLoc, ImplId, Intern, LocationCtx, ModuleDefId, ModuleId, StaticId, StructId, - StructOrUnionId, TraitId, TypeAliasId, UnionId, + StructOrUnionId, TraitId, TypeAliasContainerId, TypeAliasLoc, UnionId, }; pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) -> CrateDefMap { @@ -673,13 +673,13 @@ where let name = def.name.clone(); let def: PerNs = match def.kind { raw::DefKind::Function(ast_id) => { - let f = FunctionLoc { + let def = FunctionLoc { container: FunctionContainerId::ModuleId(module), ast_id: AstId::new(self.file_id, ast_id), } .intern(self.def_collector.db); - PerNs::values(f.into()) + PerNs::values(def.into()) } raw::DefKind::Struct(ast_id) => { let id = StructOrUnionId::from_ast_id(ctx, ast_id).into(); @@ -698,7 +698,13 @@ where } raw::DefKind::Trait(ast_id) => PerNs::types(TraitId::from_ast_id(ctx, ast_id).into()), raw::DefKind::TypeAlias(ast_id) => { - PerNs::types(TypeAliasId::from_ast_id(ctx, ast_id).into()) + let def = TypeAliasLoc { + container: TypeAliasContainerId::ModuleId(module), + ast_id: AstId::new(self.file_id, ast_id), + } + .intern(self.def_collector.db); + + PerNs::types(def.into()) } }; let resolution = Resolution { def, import: None }; diff --git a/crates/ra_hir_def/src/traits.rs b/crates/ra_hir_def/src/traits.rs index 6e36bc0d0c..228524a574 100644 --- a/crates/ra_hir_def/src/traits.rs +++ b/crates/ra_hir_def/src/traits.rs @@ -12,7 +12,7 @@ use rustc_hash::FxHashMap; use crate::{ db::DefDatabase2, AssocItemId, AstItemDef, ConstId, FunctionContainerId, FunctionLoc, Intern, - LocationCtx, ModuleDefId, ModuleId, TraitId, TypeAliasId, + LocationCtx, ModuleDefId, ModuleId, TraitId, TypeAliasContainerId, TypeAliasLoc, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -41,7 +41,12 @@ impl TraitData { .intern(db) .into(), ast::ImplItem::ConstDef(it) => ConstId::from_ast(ctx, &it).into(), - ast::ImplItem::TypeAliasDef(it) => TypeAliasId::from_ast(ctx, &it).into(), + ast::ImplItem::TypeAliasDef(it) => TypeAliasLoc { + container: TypeAliasContainerId::TraitId(tr), + ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), + } + .intern(db) + .into(), }) .collect() } else { @@ -65,6 +70,7 @@ impl TraitItemsIndex { for item in db.trait_data(tr).items.iter() { match item { AssocItemId::FunctionId(_) => (), + AssocItemId::TypeAliasId(_) => (), _ => { let prev = index.traits_by_def.insert(*item, tr); assert!(prev.is_none()); From ee95a35664e6fe9153f6324cfc57872ca365887c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 17:49:57 +0300 Subject: [PATCH 14/24] Don't duplicate ContainerId type --- crates/ra_hir/src/code_model.rs | 16 +++++----- crates/ra_hir_def/src/impls.rs | 8 ++--- crates/ra_hir_def/src/lib.rs | 37 +++++++++------------- crates/ra_hir_def/src/nameres/collector.rs | 8 ++--- crates/ra_hir_def/src/traits.rs | 8 ++--- 5 files changed, 35 insertions(+), 42 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index b8d48a500c..6696669897 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -12,8 +12,8 @@ use hir_def::{ builtin_type::BuiltinType, traits::TraitData, type_ref::{Mutability, TypeRef}, - AssocItemId, CrateModuleId, FunctionContainerId, HasModule, ImplId, LocalEnumVariantId, - LocalStructFieldId, Lookup, ModuleId, TypeAliasContainerId, UnionId, + AssocItemId, ContainerId, CrateModuleId, HasModule, ImplId, LocalEnumVariantId, + LocalStructFieldId, Lookup, ModuleId, UnionId, }; use hir_expand::{ diagnostics::DiagnosticSink, @@ -697,9 +697,9 @@ impl Function { pub fn container(self, db: &impl DefDatabase) -> Option { match self.id.lookup(db).container { - FunctionContainerId::TraitId(it) => Some(Container::Trait(it.into())), - FunctionContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())), - FunctionContainerId::ModuleId(_) => None, + ContainerId::TraitId(it) => Some(Container::Trait(it.into())), + ContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())), + ContainerId::ModuleId(_) => None, } } @@ -979,9 +979,9 @@ impl TypeAlias { pub fn container(self, db: &impl DefDatabase) -> Option { match self.id.lookup(db).container { - TypeAliasContainerId::TraitId(it) => Some(Container::Trait(it.into())), - TypeAliasContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())), - TypeAliasContainerId::ModuleId(_) => None, + ContainerId::TraitId(it) => Some(Container::Trait(it.into())), + ContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())), + ContainerId::ModuleId(_) => None, } } diff --git a/crates/ra_hir_def/src/impls.rs b/crates/ra_hir_def/src/impls.rs index 703e4d503b..574086ac72 100644 --- a/crates/ra_hir_def/src/impls.rs +++ b/crates/ra_hir_def/src/impls.rs @@ -9,8 +9,8 @@ use hir_expand::AstId; use ra_syntax::ast; use crate::{ - db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstId, FunctionContainerId, - FunctionLoc, ImplId, Intern, LocationCtx, TypeAliasContainerId, TypeAliasLoc, + db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstId, ContainerId, + FunctionLoc, ImplId, Intern, LocationCtx, TypeAliasLoc, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -37,7 +37,7 @@ impl ImplData { .map(|item_node| match item_node { ast::ImplItem::FnDef(it) => { let def = FunctionLoc { - container: FunctionContainerId::ImplId(id), + container: ContainerId::ImplId(id), ast_id: AstId::new(src.file_id, items.ast_id(&it)), } .intern(db); @@ -48,7 +48,7 @@ impl ImplData { } ast::ImplItem::TypeAliasDef(it) => { let def = TypeAliasLoc { - container: TypeAliasContainerId::ImplId(id), + container: ContainerId::ImplId(id), ast_id: AstId::new(src.file_id, items.ast_id(&it)), } .intern(db); diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 6052370b4d..da6506fcd1 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -201,7 +201,7 @@ impl_intern_key!(FunctionId); #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct FunctionLoc { - pub container: FunctionContainerId, + pub container: ContainerId, pub ast_id: AstId, } @@ -219,13 +219,6 @@ impl Lookup for FunctionId { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum FunctionContainerId { - ModuleId(ModuleId), - ImplId(ImplId), - TraitId(TraitId), -} - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct StructOrUnionId(salsa::InternId); impl_intern_key!(StructOrUnionId); @@ -335,7 +328,7 @@ impl_intern_key!(TypeAliasId); #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TypeAliasLoc { - pub container: TypeAliasContainerId, + pub container: ContainerId, pub ast_id: AstId, } @@ -353,13 +346,6 @@ impl Lookup for TypeAliasId { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum TypeAliasContainerId { - ModuleId(ModuleId), - ImplId(ImplId), - TraitId(TraitId), -} - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ImplId(salsa::InternId); impl_intern_key!(ImplId); @@ -391,6 +377,13 @@ macro_rules! impl_froms { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum ContainerId { + ModuleId(ModuleId), + ImplId(ImplId), + TraitId(TraitId), +} + /// A Data Type #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum AdtId { @@ -488,9 +481,9 @@ pub trait HasModule { impl HasModule for FunctionLoc { fn module(&self, db: &impl db::DefDatabase2) -> ModuleId { match self.container { - FunctionContainerId::ModuleId(it) => it, - FunctionContainerId::ImplId(it) => it.module(db), - FunctionContainerId::TraitId(it) => it.module(db), + ContainerId::ModuleId(it) => it, + ContainerId::ImplId(it) => it.module(db), + ContainerId::TraitId(it) => it.module(db), } } } @@ -498,9 +491,9 @@ impl HasModule for FunctionLoc { impl HasModule for TypeAliasLoc { fn module(&self, db: &impl db::DefDatabase2) -> ModuleId { match self.container { - TypeAliasContainerId::ModuleId(it) => it, - TypeAliasContainerId::ImplId(it) => it.module(db), - TypeAliasContainerId::TraitId(it) => it.module(db), + ContainerId::ModuleId(it) => it, + ContainerId::ImplId(it) => it.module(db), + ContainerId::TraitId(it) => it.module(db), } } } diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 060185b619..71e01279d7 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -19,9 +19,9 @@ use crate::{ per_ns::PerNs, raw, CrateDefMap, ModuleData, Resolution, ResolveMode, }, path::{Path, PathKind}, - AdtId, AstId, AstItemDef, ConstId, CrateModuleId, EnumId, EnumVariantId, FunctionContainerId, + AdtId, AstId, AstItemDef, ConstId, ContainerId, CrateModuleId, EnumId, EnumVariantId, FunctionLoc, ImplId, Intern, LocationCtx, ModuleDefId, ModuleId, StaticId, StructId, - StructOrUnionId, TraitId, TypeAliasContainerId, TypeAliasLoc, UnionId, + StructOrUnionId, TraitId, TypeAliasLoc, UnionId, }; pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) -> CrateDefMap { @@ -674,7 +674,7 @@ where let def: PerNs = match def.kind { raw::DefKind::Function(ast_id) => { let def = FunctionLoc { - container: FunctionContainerId::ModuleId(module), + container: ContainerId::ModuleId(module), ast_id: AstId::new(self.file_id, ast_id), } .intern(self.def_collector.db); @@ -699,7 +699,7 @@ where raw::DefKind::Trait(ast_id) => PerNs::types(TraitId::from_ast_id(ctx, ast_id).into()), raw::DefKind::TypeAlias(ast_id) => { let def = TypeAliasLoc { - container: TypeAliasContainerId::ModuleId(module), + container: ContainerId::ModuleId(module), ast_id: AstId::new(self.file_id, ast_id), } .intern(self.def_collector.db); diff --git a/crates/ra_hir_def/src/traits.rs b/crates/ra_hir_def/src/traits.rs index 228524a574..bb61e852a8 100644 --- a/crates/ra_hir_def/src/traits.rs +++ b/crates/ra_hir_def/src/traits.rs @@ -11,8 +11,8 @@ use ra_syntax::ast::{self, NameOwner}; use rustc_hash::FxHashMap; use crate::{ - db::DefDatabase2, AssocItemId, AstItemDef, ConstId, FunctionContainerId, FunctionLoc, Intern, - LocationCtx, ModuleDefId, ModuleId, TraitId, TypeAliasContainerId, TypeAliasLoc, + db::DefDatabase2, AssocItemId, AstItemDef, ConstId, ContainerId, FunctionLoc, Intern, + LocationCtx, ModuleDefId, ModuleId, TraitId, TypeAliasLoc, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -35,14 +35,14 @@ impl TraitData { .impl_items() .map(|item_node| match item_node { ast::ImplItem::FnDef(it) => FunctionLoc { - container: FunctionContainerId::TraitId(tr), + container: ContainerId::TraitId(tr), ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), } .intern(db) .into(), ast::ImplItem::ConstDef(it) => ConstId::from_ast(ctx, &it).into(), ast::ImplItem::TypeAliasDef(it) => TypeAliasLoc { - container: TypeAliasContainerId::TraitId(tr), + container: ContainerId::TraitId(tr), ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), } .intern(db) From 111891dc2dc1d2c7ea87144e8e3ddefe23fc7b6d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 18:00:01 +0300 Subject: [PATCH 15/24] Move constants to new ID This allows us to get rid of trait item index --- crates/ra_hir/src/code_model.rs | 25 +++++++----- crates/ra_hir/src/code_model/src.rs | 2 +- crates/ra_hir/src/db.rs | 1 - crates/ra_hir/src/from_source.rs | 25 ++++++++++-- crates/ra_hir/src/impl_block.rs | 8 ---- crates/ra_hir/src/source_binder.rs | 7 +++- crates/ra_hir/src/ty.rs | 5 ++- crates/ra_hir/src/ty/tests.rs | 7 +++- crates/ra_hir_def/src/body.rs | 1 + crates/ra_hir_def/src/db.rs | 9 ++--- crates/ra_hir_def/src/impls.rs | 12 ++++-- crates/ra_hir_def/src/lib.rs | 40 ++++++++++++++++--- crates/ra_hir_def/src/nameres/collector.rs | 12 +++++- crates/ra_hir_def/src/traits.rs | 45 ++++------------------ crates/ra_ide_api/src/change.rs | 1 - crates/ra_ide_api/src/hover.rs | 8 +--- 16 files changed, 119 insertions(+), 89 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 6696669897..920899dceb 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -729,7 +729,7 @@ pub struct Const { impl Const { pub fn module(self, db: &impl DefDatabase) -> Module { - Module { id: self.id.module(db) } + Module { id: self.id.lookup(db).module(db) } } pub fn krate(self, db: &impl DefDatabase) -> Option { @@ -748,22 +748,27 @@ impl Const { db.infer(self.into()) } - /// The containing impl block, if this is a method. + /// The containing impl block, if this is a type alias. pub fn impl_block(self, db: &impl DefDatabase) -> Option { - ImplBlock::containing(db, self.into()) + match self.container(db) { + Some(Container::ImplBlock(it)) => Some(it), + _ => None, + } } + /// The containing trait, if this is a trait type alias definition. pub fn parent_trait(self, db: &impl DefDatabase) -> Option { - db.trait_items_index(self.module(db).id).get_parent_trait(self.id.into()).map(Trait::from) + match self.container(db) { + Some(Container::Trait(it)) => Some(it), + _ => None, + } } pub fn container(self, db: &impl DefDatabase) -> Option { - if let Some(impl_block) = self.impl_block(db) { - Some(impl_block.into()) - } else if let Some(trait_) = self.parent_trait(db) { - Some(trait_.into()) - } else { - None + match self.id.lookup(db).container { + ContainerId::TraitId(it) => Some(Container::Trait(it.into())), + ContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())), + ContainerId::ModuleId(_) => None, } } diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs index 04675e08ef..354d2c98f2 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/code_model/src.rs @@ -120,7 +120,7 @@ impl HasSource for Function { impl HasSource for Const { type Ast = ast::ConstDef; fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source { - self.id.source(db) + self.id.lookup(db).source(db) } } impl HasSource for Static { diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 73859e1e94..5bb7961b39 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -26,7 +26,6 @@ pub use hir_def::db::{ BodyQuery, BodyWithSourceMapQuery, CrateDefMapQuery, DefDatabase2, DefDatabase2Storage, EnumDataQuery, ExprScopesQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage, RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery, TraitDataQuery, - TraitItemsIndexQuery, }; pub use hir_expand::db::{ AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index f5fdaafa37..b86307c58a 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -79,8 +79,27 @@ impl FromSource for Function { impl FromSource for Const { type Ast = ast::ConstDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { - let id = from_source(db, src)?; - Some(Const { id }) + let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? { + Container::Trait(it) => it.items(db), + Container::ImplBlock(it) => it.items(db), + Container::Module(m) => { + return m + .declarations(db) + .into_iter() + .filter_map(|it| match it { + ModuleDef::Const(it) => Some(it), + _ => None, + }) + .find(|it| same_source(&it.source(db), &src)) + } + }; + items + .into_iter() + .filter_map(|it| match it { + AssocItem::Const(it) => Some(it), + _ => None, + }) + .find(|it| same_source(&it.source(db), &src)) } } impl FromSource for Static { @@ -292,7 +311,7 @@ impl Container { /// equal if they point to exactly the same object. /// /// In general, we do not guarantee that we have exactly one instance of a -/// syntax tree for each file. We probably should add such guanratree, but, for +/// syntax tree for each file. We probably should add such guarantee, but, for /// the time being, we will use identity-less AstPtr comparison. fn same_source(s1: &Source, s2: &Source) -> bool { s1.as_ref().map(AstPtr::new) == s2.as_ref().map(AstPtr::new) diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index 0c2bb8fee3..0513f28a96 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs @@ -19,14 +19,6 @@ impl HasSource for ImplBlock { } impl ImplBlock { - pub(crate) fn containing(db: &impl DefDatabase, item: AssocItem) -> Option { - let module = item.module(db); - let crate_def_map = db.crate_def_map(module.id.krate); - crate_def_map[module.id.module_id].impls.iter().copied().map(ImplBlock::from).find(|it| { - db.impl_data(it.id).items().iter().copied().map(AssocItem::from).any(|it| it == item) - }) - } - pub fn target_trait(&self, db: &impl DefDatabase) -> Option { db.impl_data(self.id).target_trait().cloned() } diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index caa8d0082f..fd9994098b 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -71,7 +71,7 @@ fn def_with_body_from_child_node( match_ast! { match node { ast::FnDef(def) => { return Function::from_source(db, child.with_value(def)).map(DefWithBody::from); }, - ast::ConstDef(def) => { Some(Const { id: ctx.to_def(&def) }.into()) }, + ast::ConstDef(def) => { return Const::from_source(db, child.with_value(def)).map(DefWithBody::from); }, ast::StaticDef(def) => { Some(Static { id: ctx.to_def(&def) }.into()) }, _ => { None }, } @@ -428,6 +428,11 @@ impl SourceAnalyzer { pub(crate) fn inference_result(&self) -> Arc { self.infer.clone().unwrap() } + + #[cfg(test)] + pub(crate) fn analyzed_declaration(&self) -> Option { + self.body_owner + } } fn scope_for( diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 776613c7ce..36ece723f2 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -3,8 +3,6 @@ mod autoderef; pub(crate) mod primitive; -#[cfg(test)] -mod tests; pub(crate) mod traits; pub(crate) mod method_resolution; mod op; @@ -12,6 +10,9 @@ mod lower; mod infer; pub(crate) mod display; +#[cfg(test)] +mod tests; + use std::ops::Deref; use std::sync::Arc; use std::{fmt, iter, mem}; diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index abfaffb5e2..74c12a0a2d 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -11,6 +11,7 @@ use ra_syntax::{ ast::{self, AstNode}, SyntaxKind::*, }; +use rustc_hash::FxHashSet; use test_utils::covers; use crate::{ @@ -2518,7 +2519,6 @@ fn test() { [167; 179) 'GLOBAL_CONST': u32 [189; 191) 'id': u32 [194; 210) 'Foo::A..._CONST': u32 - [126; 128) '99': u32 "### ); } @@ -4742,10 +4742,13 @@ fn infer(content: &str) -> String { } }; + let mut analyzed = FxHashSet::default(); for node in source_file.syntax().descendants() { if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF { let analyzer = SourceAnalyzer::new(&db, Source::new(file_id.into(), &node), None); - infer_def(analyzer.inference_result(), analyzer.body_source_map()); + if analyzed.insert(analyzer.analyzed_declaration()) { + infer_def(analyzer.inference_result(), analyzer.body_source_map()); + } } } diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index b69d4dea65..dfb79a30ac 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -155,6 +155,7 @@ impl Body { (src.file_id, f.module(db), src.value.body().map(ast::Expr::from)) } DefWithBodyId::ConstId(c) => { + let c = c.lookup(db); let src = c.source(db); (src.file_id, c.module(db), src.value.body()) } diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index d6d32fb8c1..c6cd4369b2 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs @@ -13,8 +13,8 @@ use crate::{ raw::{ImportSourceMap, RawItems}, CrateDefMap, }, - traits::{TraitData, TraitItemsIndex}, - DefWithBodyId, EnumId, ImplId, ItemLoc, ModuleId, StructOrUnionId, TraitId, + traits::TraitData, + DefWithBodyId, EnumId, ImplId, ItemLoc, StructOrUnionId, TraitId, }; #[salsa::query_group(InternDatabaseStorage)] @@ -26,7 +26,7 @@ pub trait InternDatabase: SourceDatabase { #[salsa::interned] fn intern_enum(&self, loc: ItemLoc) -> crate::EnumId; #[salsa::interned] - fn intern_const(&self, loc: ItemLoc) -> crate::ConstId; + fn intern_const(&self, loc: crate::ConstLoc) -> crate::ConstId; #[salsa::interned] fn intern_static(&self, loc: ItemLoc) -> crate::StaticId; #[salsa::interned] @@ -63,9 +63,6 @@ pub trait DefDatabase2: InternDatabase + AstDatabase { #[salsa::invoke(TraitData::trait_data_query)] fn trait_data(&self, e: TraitId) -> Arc; - #[salsa::invoke(TraitItemsIndex::trait_items_index)] - fn trait_items_index(&self, module: ModuleId) -> TraitItemsIndex; - #[salsa::invoke(Body::body_with_source_map_query)] fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc, Arc); diff --git a/crates/ra_hir_def/src/impls.rs b/crates/ra_hir_def/src/impls.rs index 574086ac72..750a869f25 100644 --- a/crates/ra_hir_def/src/impls.rs +++ b/crates/ra_hir_def/src/impls.rs @@ -9,8 +9,8 @@ use hir_expand::AstId; use ra_syntax::ast; use crate::{ - db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstId, ContainerId, - FunctionLoc, ImplId, Intern, LocationCtx, TypeAliasLoc, + db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstLoc, ContainerId, + FunctionLoc, ImplId, Intern, TypeAliasLoc, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -31,7 +31,6 @@ impl ImplData { let negative = src.value.is_negative(); let items = if let Some(item_list) = src.value.item_list() { - let ctx = LocationCtx::new(db, id.module(db), src.file_id); item_list .impl_items() .map(|item_node| match item_node { @@ -44,7 +43,12 @@ impl ImplData { def.into() } ast::ImplItem::ConstDef(it) => { - ConstId::from_ast_id(ctx, items.ast_id(&it)).into() + let def = ConstLoc { + container: ContainerId::ImplId(id), + ast_id: AstId::new(src.file_id, items.ast_id(&it)), + } + .intern(db); + def.into() } ast::ImplItem::TypeAliasDef(it) => { let def = TypeAliasLoc { diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index da6506fcd1..0af41de879 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -289,12 +289,23 @@ impl_arena_id!(LocalStructFieldId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ConstId(salsa::InternId); impl_intern_key!(ConstId); -impl AstItemDef for ConstId { - fn intern(db: &impl InternDatabase, loc: ItemLoc) -> Self { - db.intern_const(loc) +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ConstLoc { + pub container: ContainerId, + pub ast_id: AstId, +} + +impl Intern for ConstLoc { + type ID = ConstId; + fn intern(self, db: &impl db::DefDatabase2) -> ConstId { + db.intern_const(self) } - fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc { - db.lookup_intern_const(self) +} + +impl Lookup for ConstId { + type Data = ConstLoc; + fn lookup(&self, db: &impl db::DefDatabase2) -> ConstLoc { + db.lookup_intern_const(*self) } } @@ -498,6 +509,16 @@ impl HasModule for TypeAliasLoc { } } +impl HasModule for ConstLoc { + fn module(&self, db: &impl db::DefDatabase2) -> ModuleId { + match self.container { + ContainerId::ModuleId(it) => it, + ContainerId::ImplId(it) => it.module(db), + ContainerId::TraitId(it) => it.module(db), + } + } +} + pub trait HasSource { type Value; fn source(&self, db: &impl db::DefDatabase2) -> Source; @@ -520,3 +541,12 @@ impl HasSource for TypeAliasLoc { Source::new(self.ast_id.file_id(), node) } } + +impl HasSource for ConstLoc { + type Value = ast::ConstDef; + + fn source(&self, db: &impl db::DefDatabase2) -> Source { + let node = self.ast_id.to_node(db); + Source::new(self.ast_id.file_id(), node) + } +} diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 71e01279d7..aae3dcadf7 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -19,7 +19,7 @@ use crate::{ per_ns::PerNs, raw, CrateDefMap, ModuleData, Resolution, ResolveMode, }, path::{Path, PathKind}, - AdtId, AstId, AstItemDef, ConstId, ContainerId, CrateModuleId, EnumId, EnumVariantId, + AdtId, AstId, AstItemDef, ConstLoc, ContainerId, CrateModuleId, EnumId, EnumVariantId, FunctionLoc, ImplId, Intern, LocationCtx, ModuleDefId, ModuleId, StaticId, StructId, StructOrUnionId, TraitId, TypeAliasLoc, UnionId, }; @@ -692,7 +692,15 @@ where PerNs::both(u, u) } raw::DefKind::Enum(ast_id) => PerNs::types(EnumId::from_ast_id(ctx, ast_id).into()), - raw::DefKind::Const(ast_id) => PerNs::values(ConstId::from_ast_id(ctx, ast_id).into()), + raw::DefKind::Const(ast_id) => { + let def = ConstLoc { + container: ContainerId::ModuleId(module), + ast_id: AstId::new(self.file_id, ast_id), + } + .intern(self.def_collector.db); + + PerNs::values(def.into()) + } raw::DefKind::Static(ast_id) => { PerNs::values(StaticId::from_ast_id(ctx, ast_id).into()) } diff --git a/crates/ra_hir_def/src/traits.rs b/crates/ra_hir_def/src/traits.rs index bb61e852a8..877d73d666 100644 --- a/crates/ra_hir_def/src/traits.rs +++ b/crates/ra_hir_def/src/traits.rs @@ -8,11 +8,10 @@ use hir_expand::{ }; use ra_syntax::ast::{self, NameOwner}; -use rustc_hash::FxHashMap; use crate::{ - db::DefDatabase2, AssocItemId, AstItemDef, ConstId, ContainerId, FunctionLoc, Intern, - LocationCtx, ModuleDefId, ModuleId, TraitId, TypeAliasLoc, + db::DefDatabase2, AssocItemId, AstItemDef, ConstLoc, ContainerId, FunctionLoc, Intern, TraitId, + TypeAliasLoc, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -26,8 +25,6 @@ impl TraitData { pub(crate) fn trait_data_query(db: &impl DefDatabase2, tr: TraitId) -> Arc { let src = tr.source(db); let name = src.value.name().map(|n| n.as_name()); - let module = tr.module(db); - let ctx = LocationCtx::new(db, module, src.file_id); let auto = src.value.is_auto(); let ast_id_map = db.ast_id_map(src.file_id); let items = if let Some(item_list) = src.value.item_list() { @@ -40,7 +37,12 @@ impl TraitData { } .intern(db) .into(), - ast::ImplItem::ConstDef(it) => ConstId::from_ast(ctx, &it).into(), + ast::ImplItem::ConstDef(it) => ConstLoc { + container: ContainerId::TraitId(tr), + ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), + } + .intern(db) + .into(), ast::ImplItem::TypeAliasDef(it) => TypeAliasLoc { container: ContainerId::TraitId(tr), ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), @@ -55,34 +57,3 @@ impl TraitData { Arc::new(TraitData { name, items, auto }) } } - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct TraitItemsIndex { - traits_by_def: FxHashMap, -} - -impl TraitItemsIndex { - pub fn trait_items_index(db: &impl DefDatabase2, module: ModuleId) -> TraitItemsIndex { - let mut index = TraitItemsIndex { traits_by_def: FxHashMap::default() }; - let crate_def_map = db.crate_def_map(module.krate); - for decl in crate_def_map[module.module_id].scope.declarations() { - if let ModuleDefId::TraitId(tr) = decl { - for item in db.trait_data(tr).items.iter() { - match item { - AssocItemId::FunctionId(_) => (), - AssocItemId::TypeAliasId(_) => (), - _ => { - let prev = index.traits_by_def.insert(*item, tr); - assert!(prev.is_none()); - } - } - } - } - } - index - } - - pub fn get_parent_trait(&self, item: AssocItemId) -> Option { - self.traits_by_def.get(&item).cloned() - } -} diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs index 5c9dec13ef..3c607d5b53 100644 --- a/crates/ra_ide_api/src/change.rs +++ b/crates/ra_ide_api/src/change.rs @@ -309,7 +309,6 @@ impl RootDatabase { hir::db::StructDataQuery hir::db::EnumDataQuery hir::db::TraitDataQuery - hir::db::TraitItemsIndexQuery hir::db::RawItemsWithSourceMapQuery hir::db::RawItemsQuery hir::db::CrateDefMapQuery diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index ae87ab9f91..9839be985f 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs @@ -404,9 +404,7 @@ mod tests { check_hover_result( r#" //- /main.rs - fn main() { - const foo<|>: u32 = 0; - } + const foo<|>: u32 = 0; "#, &["const foo: u32"], ); @@ -414,9 +412,7 @@ mod tests { check_hover_result( r#" //- /main.rs - fn main() { - static foo<|>: u32 = 0; - } + static foo<|>: u32 = 0; "#, &["static foo: u32"], ); From cb642fc578100c0945088accb85acb8f03d2e1fd Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 20:33:18 +0300 Subject: [PATCH 16/24] Move generic_params query to HIR --- crates/ra_hir/src/db.rs | 10 ++++------ crates/ra_hir/src/generics.rs | 19 ++----------------- crates/ra_hir_def/src/db.rs | 6 +++++- crates/ra_hir_def/src/generics.rs | 29 ++++++++++++++++++++++++++--- 4 files changed, 37 insertions(+), 27 deletions(-) diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 5bb7961b39..a9982a70f6 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -8,7 +8,7 @@ use ra_syntax::SmolStr; use crate::{ debug::HirDebugDatabase, - generics::{GenericDef, GenericParams}, + generics::GenericDef, ids, lang_item::{LangItemTarget, LangItems}, ty::{ @@ -24,8 +24,9 @@ use crate::{ pub use hir_def::db::{ BodyQuery, BodyWithSourceMapQuery, CrateDefMapQuery, DefDatabase2, DefDatabase2Storage, - EnumDataQuery, ExprScopesQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage, - RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery, TraitDataQuery, + EnumDataQuery, ExprScopesQuery, GenericParamsQuery, ImplDataQuery, InternDatabase, + InternDatabaseStorage, RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery, + TraitDataQuery, }; pub use hir_expand::db::{ AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, @@ -36,9 +37,6 @@ pub use hir_expand::db::{ #[salsa::query_group(DefDatabaseStorage)] #[salsa::requires(AstDatabase)] pub trait DefDatabase: HirDebugDatabase + DefDatabase2 { - #[salsa::invoke(crate::generics::generic_params_query)] - fn generic_params(&self, def: GenericDef) -> Arc; - #[salsa::invoke(FnData::fn_data_query)] fn fn_data(&self, func: Function) -> Arc; diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index caedb90e6a..54ed03642a 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use crate::{ - db::{AstDatabase, DefDatabase, HirDatabase}, + db::{DefDatabase, HirDatabase}, Adt, Const, Container, Enum, EnumVariant, Function, ImplBlock, Struct, Trait, TypeAlias, Union, }; @@ -31,21 +31,6 @@ impl_froms!( Const ); -pub(crate) fn generic_params_query( - db: &(impl DefDatabase + AstDatabase), - def: GenericDef, -) -> Arc { - let parent = match def { - GenericDef::Function(it) => it.container(db).map(GenericDef::from), - GenericDef::TypeAlias(it) => it.container(db).map(GenericDef::from), - GenericDef::Const(it) => it.container(db).map(GenericDef::from), - GenericDef::EnumVariant(it) => Some(it.parent_enum(db).into()), - GenericDef::Adt(_) | GenericDef::Trait(_) => None, - GenericDef::ImplBlock(_) => None, - }; - Arc::new(GenericParams::new(db, def.into(), parent.map(|it| db.generic_params(it)))) -} - impl GenericDef { pub(crate) fn resolver(&self, db: &impl HirDatabase) -> crate::Resolver { match self { @@ -78,6 +63,6 @@ where T: Into + Copy, { fn generic_params(self, db: &impl DefDatabase) -> Arc { - db.generic_params(self.into()) + db.generic_params(self.into().into()) } } diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index c6cd4369b2..844f8bbe88 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs @@ -8,13 +8,14 @@ use ra_syntax::ast; use crate::{ adt::{EnumData, StructData}, body::{scope::ExprScopes, Body, BodySourceMap}, + generics::GenericParams, impls::ImplData, nameres::{ raw::{ImportSourceMap, RawItems}, CrateDefMap, }, traits::TraitData, - DefWithBodyId, EnumId, ImplId, ItemLoc, StructOrUnionId, TraitId, + DefWithBodyId, EnumId, GenericDefId, ImplId, ItemLoc, StructOrUnionId, TraitId, }; #[salsa::query_group(InternDatabaseStorage)] @@ -71,4 +72,7 @@ pub trait DefDatabase2: InternDatabase + AstDatabase { #[salsa::invoke(ExprScopes::expr_scopes_query)] fn expr_scopes(&self, def: DefWithBodyId) -> Arc; + + #[salsa::invoke(GenericParams::generic_params_query)] + fn generic_params(&self, def: GenericDefId) -> Arc; } diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index 17a5d5f436..f794eefbcd 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs @@ -5,13 +5,12 @@ use std::sync::Arc; use hir_expand::name::{self, AsName, Name}; - use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; use crate::{ db::DefDatabase2, type_ref::{TypeBound, TypeRef}, - AdtId, AstItemDef, GenericDefId, HasSource, Lookup, + AdtId, AstItemDef, ContainerId, GenericDefId, HasSource, Lookup, }; /// Data about a generic parameter (to a function, struct, impl, ...). @@ -43,7 +42,15 @@ pub struct WherePredicate { } impl GenericParams { - pub fn new( + pub(crate) fn generic_params_query( + db: &impl DefDatabase2, + def: GenericDefId, + ) -> Arc { + let parent_generics = parent_generic_def(db, def).map(|it| db.generic_params(it)); + Arc::new(GenericParams::new(db, def.into(), parent_generics)) + } + + fn new( db: &impl DefDatabase2, def: GenericDefId, parent_params: Option>, @@ -161,3 +168,19 @@ impl GenericParams { vec } } + +fn parent_generic_def(db: &impl DefDatabase2, def: GenericDefId) -> Option { + let container = match def { + GenericDefId::FunctionId(it) => it.lookup(db).container, + GenericDefId::TypeAliasId(it) => it.lookup(db).container, + GenericDefId::ConstId(it) => it.lookup(db).container, + GenericDefId::EnumVariantId(it) => return Some(it.parent.into()), + GenericDefId::AdtId(_) | GenericDefId::TraitId(_) | GenericDefId::ImplId(_) => return None, + }; + + match container { + ContainerId::ImplId(it) => Some(it.into()), + ContainerId::TraitId(it) => Some(it.into()), + ContainerId::ModuleId(_) => None, + } +} From 12ec946216a3637685f30ae359bc955313595a22 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 20:50:34 +0300 Subject: [PATCH 17/24] Simplify generic params --- crates/ra_hir/src/code_model.rs | 23 +++++------------- crates/ra_hir/src/impl_block.rs | 8 +++---- crates/ra_hir/src/resolve.rs | 39 +++++++++++++++++++------------ crates/ra_hir_def/src/generics.rs | 3 +-- 4 files changed, 34 insertions(+), 39 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 920899dceb..e2638cf92f 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -322,9 +322,7 @@ impl Struct { // take the outer scope... let r = self.module(db).resolver(db); // ...and add generic params, if present - let p = self.generic_params(db); - let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; - r + r.push_generic_params_scope(db, self.into()) } } @@ -352,9 +350,7 @@ impl Union { // take the outer scope... let r = self.module(db).resolver(db); // ...and add generic params, if present - let p = self.generic_params(db); - let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; - r + r.push_generic_params_scope(db, self.into()) } } @@ -402,8 +398,7 @@ impl Enum { // take the outer scope... let r = self.module(db).resolver(db); // ...and add generic params, if present - let p = self.generic_params(db); - let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; + let r = r.push_generic_params_scope(db, self.into()); r.push_scope(Scope::AdtScope(self.into())) } } @@ -709,9 +704,7 @@ impl Function { // take the outer scope... let r = self.container(db).map_or_else(|| self.module(db).resolver(db), |c| c.resolver(db)); // ...and add generic params, if present - let p = self.generic_params(db); - let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; - r + r.push_generic_params_scope(db, self.into()) } pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) { @@ -946,9 +939,7 @@ impl Trait { pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver { let r = self.module(db).resolver(db); // add generic params, if present - let p = self.generic_params(db); - let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; - r + r.push_generic_params_scope(db, self.into()) } } @@ -1010,9 +1001,7 @@ impl TypeAlias { .map(|ib| ib.resolver(db)) .unwrap_or_else(|| self.module(db).resolver(db)); // ...and add generic params, if present - let p = self.generic_params(db); - let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; - r + r.push_generic_params_scope(db, self.into()) } } diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index 0513f28a96..492d964a43 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs @@ -5,7 +5,6 @@ use ra_syntax::ast::{self}; use crate::{ db::{AstDatabase, DefDatabase, HirDatabase}, - generics::HasGenericParams, resolve::Resolver, ty::Ty, AssocItem, Crate, HasSource, ImplBlock, Module, Source, TraitRef, @@ -52,12 +51,11 @@ impl ImplBlock { Crate { crate_id: self.module(db).id.krate } } - pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { + pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver { let r = self.module(db).resolver(db); // add generic params, if present - let p = self.generic_params(db); - let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; - let r = r.push_impl_block_scope(self.clone()); + let r = r.push_generic_params_scope(db, self.into()); + let r = r.push_impl_block_scope(self); r } } diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index a2fa0bb79e..e5e768be90 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs @@ -14,9 +14,9 @@ use crate::{ code_model::Crate, db::{DefDatabase, HirDatabase}, expr::{ExprScopes, PatId, ScopeId}, - generics::GenericParams, - Adt, Const, DefWithBody, Enum, EnumVariant, Function, ImplBlock, Local, MacroDef, ModuleDef, - PerNs, Static, Struct, Trait, TypeAlias, + generics::{GenericParams, HasGenericParams}, + Adt, Const, DefWithBody, Enum, EnumVariant, Function, GenericDef, ImplBlock, Local, MacroDef, + ModuleDef, PerNs, Static, Struct, Trait, TypeAlias, }; #[derive(Debug, Clone, Default)] @@ -43,7 +43,7 @@ pub(crate) enum Scope { /// All the items and imported names of a module ModuleScope(ModuleItemMap), /// Brings the generic parameters of an item into scope - GenericParams(Arc), + GenericParams { def: GenericDef, params: Arc }, /// Brings `Self` in `impl` block into scope ImplBlockScope(ImplBlock), /// Brings `Self` in enum, struct and union definitions into scope @@ -141,9 +141,9 @@ impl Resolver { for scope in self.scopes.iter().rev() { match scope { Scope::ExprScope(_) => continue, - Scope::GenericParams(_) | Scope::ImplBlockScope(_) if skip_to_mod => continue, + Scope::GenericParams { .. } | Scope::ImplBlockScope(_) if skip_to_mod => continue, - Scope::GenericParams(params) => { + Scope::GenericParams { params, .. } => { if let Some(param) = params.find_by_name(first_name) { let idx = if path.segments.len() == 1 { None } else { Some(1) }; return Some((TypeNs::GenericParam(param.idx), idx)); @@ -212,7 +212,7 @@ impl Resolver { match scope { Scope::AdtScope(_) | Scope::ExprScope(_) - | Scope::GenericParams(_) + | Scope::GenericParams { .. } | Scope::ImplBlockScope(_) if skip_to_mod => { @@ -232,13 +232,13 @@ impl Resolver { } Scope::ExprScope(_) => continue, - Scope::GenericParams(params) if n_segments > 1 => { + Scope::GenericParams { params, .. } if n_segments > 1 => { if let Some(param) = params.find_by_name(first_name) { let ty = TypeNs::GenericParam(param.idx); return Some(ResolveValueResult::Partial(ty, 1)); } } - Scope::GenericParams(_) => continue, + Scope::GenericParams { .. } => continue, Scope::ImplBlockScope(impl_) if n_segments > 1 => { if first_name == &name::SELF_TYPE { @@ -361,7 +361,7 @@ impl Resolver { self.scopes .iter() .filter_map(|scope| match scope { - Scope::GenericParams(params) => Some(params), + Scope::GenericParams { params, .. } => Some(params), _ => None, }) .flat_map(|params| params.where_predicates.iter()) @@ -369,7 +369,7 @@ impl Resolver { pub(crate) fn generic_def(&self) -> Option { self.scopes.iter().find_map(|scope| match scope { - Scope::GenericParams(params) => Some(params.def.into()), + Scope::GenericParams { def, .. } => Some(*def), _ => None, }) } @@ -381,8 +381,17 @@ impl Resolver { self } - pub(crate) fn push_generic_params_scope(self, params: Arc) -> Resolver { - self.push_scope(Scope::GenericParams(params)) + pub(crate) fn push_generic_params_scope( + self, + db: &impl DefDatabase, + def: GenericDef, + ) -> Resolver { + let params = def.generic_params(db); + if params.params.is_empty() { + self + } else { + self.push_scope(Scope::GenericParams { def, params }) + } } pub(crate) fn push_impl_block_scope(self, impl_block: ImplBlock) -> Resolver { @@ -457,8 +466,8 @@ impl Scope { }); } } - Scope::GenericParams(gp) => { - for param in &gp.params { + Scope::GenericParams { params, .. } => { + for param in params.params.iter() { f(param.name.clone(), ScopeDef::GenericParam(param.idx)) } } diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index f794eefbcd..9e2e4c3cc3 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs @@ -25,7 +25,6 @@ pub struct GenericParam { /// Data about the generic parameters of a function, struct, impl, etc. #[derive(Clone, PartialEq, Eq, Debug)] pub struct GenericParams { - pub def: GenericDefId, pub parent_params: Option>, pub params: Vec, pub where_predicates: Vec, @@ -56,7 +55,7 @@ impl GenericParams { parent_params: Option>, ) -> GenericParams { let mut generics = - GenericParams { def, params: Vec::new(), parent_params, where_predicates: Vec::new() }; + GenericParams { params: Vec::new(), parent_params, where_predicates: Vec::new() }; let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; // FIXME: add `: Sized` bound for everything except for `Self` in traits match def { From bcb2ea912bf96f38505c67a0b6896c6a5ac278ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Kohlgr=C3=BCber?= Date: Wed, 20 Nov 2019 19:01:06 +0100 Subject: [PATCH 18/24] fix 2190; add test for "replace if let with match" --- .../src/assists/replace_if_let_with_match.rs | 32 +++++++++++++++++-- crates/ra_fmt/src/lib.rs | 3 -- crates/ra_ide_api/src/join_lines.rs | 28 ++++++++++++++++ 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/crates/ra_assists/src/assists/replace_if_let_with_match.rs b/crates/ra_assists/src/assists/replace_if_let_with_match.rs index dff84d8651..3272801ff8 100644 --- a/crates/ra_assists/src/assists/replace_if_let_with_match.rs +++ b/crates/ra_assists/src/assists/replace_if_let_with_match.rs @@ -66,8 +66,8 @@ fn build_match_expr( fn format_arm(block: &ast::BlockExpr) -> String { match extract_trivial_expression(block) { - None => block.syntax().text().to_string(), - Some(e) => format!("{},", e.syntax().text()), + Some(e) if !e.syntax().text().contains_char('\n') => format!("{},", e.syntax().text()), + _ => block.syntax().text().to_string(), } } @@ -102,6 +102,34 @@ impl VariantData { ) } + #[test] + fn test_replace_if_let_with_match_doesnt_unwrap_multiline_expressions() { + check_assist( + replace_if_let_with_match, + " +fn foo() { + if <|>let VariantData::Struct(..) = a { + bar( + 123 + ) + } else { + false + } +} ", + " +fn foo() { + <|>match a { + VariantData::Struct(..) => { + bar( + 123 + ) + } + _ => false, + } +} ", + ) + } + #[test] fn replace_if_let_with_match_target() { check_assist_target( diff --git a/crates/ra_fmt/src/lib.rs b/crates/ra_fmt/src/lib.rs index a30ed4cbb8..10f592257c 100644 --- a/crates/ra_fmt/src/lib.rs +++ b/crates/ra_fmt/src/lib.rs @@ -38,9 +38,6 @@ fn prev_tokens(token: SyntaxToken) -> impl Iterator { pub fn extract_trivial_expression(expr: &ast::BlockExpr) -> Option { let block = expr.block()?; let expr = block.expr()?; - if expr.syntax().text().contains_char('\n') { - return None; - } let non_trivial_children = block.syntax().children().filter(|it| match it.kind() { WHITESPACE | T!['{'] | T!['}'] => false, _ => it != expr.syntax(), diff --git a/crates/ra_ide_api/src/join_lines.rs b/crates/ra_ide_api/src/join_lines.rs index 6f71b27db2..7deeb34947 100644 --- a/crates/ra_ide_api/src/join_lines.rs +++ b/crates/ra_ide_api/src/join_lines.rs @@ -243,6 +243,34 @@ fn foo(e: Result) { ); } + #[test] + fn join_lines_multiline_in_block() { + check_join_lines( + r" +fn foo() { + match ty { + <|> Some(ty) => { + match ty { + _ => false, + } + } + _ => true, + } +} +", + r" +fn foo() { + match ty { + <|> Some(ty) => match ty { + _ => false, + }, + _ => true, + } +} +", + ); + } + #[test] fn join_lines_keeps_comma_for_block_in_match_arm() { // We already have a comma From 7c275a7ed2253fc7bd8b46c685a754c4d4e9dee3 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 21:08:39 +0300 Subject: [PATCH 19/24] Remove hir/adt.rs --- crates/ra_hir/src/adt.rs | 54 ----------------------------- crates/ra_hir/src/code_model.rs | 42 +++++++++++++++++++++- crates/ra_hir/src/code_model/src.rs | 3 +- crates/ra_hir/src/lib.rs | 8 ++--- crates/ra_hir/src/ty/infer.rs | 3 +- crates/ra_hir/src/ty/lower.rs | 3 +- 6 files changed, 47 insertions(+), 66 deletions(-) delete mode 100644 crates/ra_hir/src/adt.rs diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs deleted file mode 100644 index 945f236c22..0000000000 --- a/crates/ra_hir/src/adt.rs +++ /dev/null @@ -1,54 +0,0 @@ -//! This module contains the implementation details of the HIR for ADTs, i.e. -//! structs and enums (and unions). - -use std::sync::Arc; - -use hir_def::adt::VariantData; - -use crate::{ - db::{DefDatabase, HirDatabase}, - EnumVariant, Module, Name, Struct, StructField, -}; - -impl Struct { - pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc { - db.struct_data(self.id.into()).variant_data.clone() - } -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub enum VariantDef { - Struct(Struct), - EnumVariant(EnumVariant), -} -impl_froms!(VariantDef: Struct, EnumVariant); - -impl VariantDef { - pub fn fields(self, db: &impl HirDatabase) -> Vec { - match self { - VariantDef::Struct(it) => it.fields(db), - VariantDef::EnumVariant(it) => it.fields(db), - } - } - - pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option { - match self { - VariantDef::Struct(it) => it.field(db, name), - VariantDef::EnumVariant(it) => it.field(db, name), - } - } - - pub fn module(self, db: &impl HirDatabase) -> Module { - match self { - VariantDef::Struct(it) => it.module(db), - VariantDef::EnumVariant(it) => it.module(db), - } - } - - pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc { - match self { - VariantDef::Struct(it) => it.variant_data(db), - VariantDef::EnumVariant(it) => it.variant_data(db), - } - } -} diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index e2638cf92f..9b6276b51b 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -23,7 +23,6 @@ use ra_db::{CrateId, Edition}; use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; use crate::{ - adt::VariantDef, db::{AstDatabase, DefDatabase, HirDatabase}, expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, generics::{GenericDef, HasGenericParams}, @@ -324,6 +323,10 @@ impl Struct { // ...and add generic params, if present r.push_generic_params_scope(db, self.into()) } + + fn variant_data(self, db: &impl DefDatabase) -> Arc { + db.struct_data(self.id.into()).variant_data.clone() + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -482,6 +485,43 @@ impl Adt { } } +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum VariantDef { + Struct(Struct), + EnumVariant(EnumVariant), +} +impl_froms!(VariantDef: Struct, EnumVariant); + +impl VariantDef { + pub fn fields(self, db: &impl HirDatabase) -> Vec { + match self { + VariantDef::Struct(it) => it.fields(db), + VariantDef::EnumVariant(it) => it.fields(db), + } + } + + pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option { + match self { + VariantDef::Struct(it) => it.field(db, name), + VariantDef::EnumVariant(it) => it.field(db, name), + } + } + + pub fn module(self, db: &impl HirDatabase) -> Module { + match self { + VariantDef::Struct(it) => it.module(db), + VariantDef::EnumVariant(it) => it.module(db), + } + } + + pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc { + match self { + VariantDef::Struct(it) => it.variant_data(db), + VariantDef::EnumVariant(it) => it.variant_data(db), + } + } +} + /// The defs which have a body. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum DefWithBody { diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs index 354d2c98f2..4aa427de43 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/code_model/src.rs @@ -4,11 +4,10 @@ use hir_def::{HasSource as _, Lookup}; use ra_syntax::ast::{self, AstNode}; use crate::{ - adt::VariantDef, db::{AstDatabase, DefDatabase, HirDatabase}, ids::AstItemDef, Const, Either, Enum, EnumVariant, FieldSource, Function, HasBody, HirFileId, MacroDef, Module, - ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union, + ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef, }; pub use hir_expand::Source; diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 7ac9a90414..31da74d2f3 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -32,7 +32,6 @@ pub mod db; pub mod source_binder; mod ids; -mod adt; mod type_alias; mod ty; mod impl_block; @@ -56,15 +55,14 @@ mod marks; use crate::resolve::Resolver; pub use crate::{ - adt::VariantDef, - code_model::ImplBlock, code_model::{ attrs::{AttrDef, Attrs}, docs::{DocDef, Docs, Documentation}, src::{HasBodySource, HasSource}, Adt, AssocItem, Const, ConstData, Container, Crate, CrateDependency, DefWithBody, Enum, - EnumVariant, FieldSource, FnData, Function, GenericParam, HasBody, Local, MacroDef, Module, - ModuleDef, ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union, + EnumVariant, FieldSource, FnData, Function, GenericParam, HasBody, ImplBlock, Local, + MacroDef, Module, ModuleDef, ModuleSource, Static, Struct, StructField, Trait, TypeAlias, + Union, VariantDef, }, expr::ExprScopes, from_source::FromSource, diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index c35378cc41..092bc3a3f2 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -37,14 +37,13 @@ use super::{ TypeCtor, TypeWalk, Uncertain, }; use crate::{ - adt::VariantDef, code_model::TypeAlias, db::HirDatabase, expr::{BindingAnnotation, Body, ExprId, PatId}, resolve::{Resolver, TypeNs}, ty::infer::diagnostics::InferenceDiagnostic, Adt, AssocItem, ConstData, DefWithBody, FloatTy, FnData, Function, HasBody, IntTy, Path, - StructField, + StructField, VariantDef, }; macro_rules! ty_app { diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 03db386055..91e60b5ab4 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs @@ -19,7 +19,6 @@ use super::{ TypeWalk, }; use crate::{ - adt::VariantDef, db::HirDatabase, generics::HasGenericParams, generics::{GenericDef, WherePredicate}, @@ -30,7 +29,7 @@ use crate::{ }, util::make_mut_slice, Const, Enum, EnumVariant, Function, ModuleDef, Path, Static, Struct, StructField, Trait, - TypeAlias, Union, + TypeAlias, Union, VariantDef, }; // FIXME: this is only really used in `type_for_def`, which contains a bunch of From 6241cf9a598b19cbd6c8c41c3743f8d56adafd2b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 21:55:33 +0300 Subject: [PATCH 20/24] Add HasResolver trait --- crates/ra_hir/src/code_model.rs | 106 +------------- crates/ra_hir/src/expr.rs | 1 + crates/ra_hir/src/generics.rs | 18 +-- crates/ra_hir/src/impl_block.rs | 10 +- crates/ra_hir/src/resolve.rs | 131 +++++++++++++++++- crates/ra_hir/src/source_binder.rs | 2 +- crates/ra_hir/src/ty/infer.rs | 2 +- crates/ra_hir/src/ty/lower.rs | 2 +- .../src/completion/complete_scope.rs | 7 + 9 files changed, 145 insertions(+), 134 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 9b6276b51b..c5539e0764 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -30,7 +30,7 @@ use crate::{ AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId, TypeAliasId, }, - resolve::{Resolver, Scope, TypeNs}, + resolve::{HasResolver, TypeNs}, ty::{InferenceResult, Namespace, TraitRef}, Either, HasSource, ImportId, Name, ScopeDef, Source, Ty, }; @@ -223,11 +223,6 @@ impl Module { } } - pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver { - let def_map = db.crate_def_map(self.id.krate); - Resolver::default().push_module_scope(def_map, self.id.module_id) - } - pub fn declarations(self, db: &impl DefDatabase) -> Vec { let def_map = db.crate_def_map(self.id.krate); def_map[self.id.module_id].scope.declarations().map(ModuleDef::from).collect() @@ -315,15 +310,6 @@ impl Struct { db.type_for_def(self.into(), Namespace::Values) } - // FIXME move to a more general type - /// Builds a resolver for type references inside this struct. - pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver { - // take the outer scope... - let r = self.module(db).resolver(db); - // ...and add generic params, if present - r.push_generic_params_scope(db, self.into()) - } - fn variant_data(self, db: &impl DefDatabase) -> Arc { db.struct_data(self.id.into()).variant_data.clone() } @@ -339,22 +325,13 @@ impl Union { db.struct_data(self.id.into()).name.clone() } - pub fn module(self, db: &impl HirDatabase) -> Module { + pub fn module(self, db: &impl DefDatabase) -> Module { Module { id: self.id.0.module(db) } } pub fn ty(self, db: &impl HirDatabase) -> Ty { db.type_for_def(self.into(), Namespace::Types) } - - // FIXME move to a more general type - /// Builds a resolver for type references inside this union. - pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver { - // take the outer scope... - let r = self.module(db).resolver(db); - // ...and add generic params, if present - r.push_generic_params_scope(db, self.into()) - } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -394,16 +371,6 @@ impl Enum { pub fn ty(self, db: &impl HirDatabase) -> Ty { db.type_for_def(self.into(), Namespace::Types) } - - // FIXME: move to a more general type - /// Builds a resolver for type references inside this struct. - pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver { - // take the outer scope... - let r = self.module(db).resolver(db); - // ...and add generic params, if present - let r = r.push_generic_params_scope(db, self.into()); - r.push_scope(Scope::AdtScope(self.into())) - } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -475,14 +442,6 @@ impl Adt { .krate(), ) } - - pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver { - match self { - Adt::Struct(it) => it.resolver(db), - Adt::Union(it) => it.resolver(db), - Adt::Enum(it) => it.resolver(db), - } - } } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] @@ -533,15 +492,6 @@ pub enum DefWithBody { impl_froms!(DefWithBody: Function, Const, Static); impl DefWithBody { - /// Builds a resolver for code inside this item. - pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver { - match self { - DefWithBody::Const(c) => c.resolver(db), - DefWithBody::Function(f) => f.resolver(db), - DefWithBody::Static(s) => s.resolver(db), - } - } - pub(crate) fn krate(self, db: &impl HirDatabase) -> Option { match self { DefWithBody::Const(c) => c.krate(db), @@ -738,15 +688,6 @@ impl Function { } } - // FIXME: move to a more general type for 'body-having' items - /// Builds a resolver for code inside this item. - pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver { - // take the outer scope... - let r = self.container(db).map_or_else(|| self.module(db).resolver(db), |c| c.resolver(db)); - // ...and add generic params, if present - r.push_generic_params_scope(db, self.into()) - } - pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) { let infer = self.infer(db); infer.add_diagnostics(db, self, sink); @@ -804,17 +745,6 @@ impl Const { ContainerId::ModuleId(_) => None, } } - - // FIXME: move to a more general type for 'body-having' items - /// Builds a resolver for code inside this item. - pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver { - // take the outer scope... - let r = self - .impl_block(db) - .map(|ib| ib.resolver(db)) - .unwrap_or_else(|| self.module(db).resolver(db)); - r - } } #[derive(Debug, Clone, PartialEq, Eq)] @@ -874,12 +804,6 @@ impl Static { db.static_data(self) } - /// Builds a resolver for code inside this item. - pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver { - // take the outer scope... - self.module(db).resolver(db) - } - pub fn infer(self, db: &impl HirDatabase) -> Arc { db.infer(self.into()) } @@ -975,12 +899,6 @@ impl Trait { pub fn is_auto(self, db: &impl DefDatabase) -> bool { self.trait_data(db).auto } - - pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver { - let r = self.module(db).resolver(db); - // add generic params, if present - r.push_generic_params_scope(db, self.into()) - } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -1032,17 +950,6 @@ impl TypeAlias { pub fn name(self, db: &impl DefDatabase) -> Name { db.type_alias_data(self).name.clone() } - - /// Builds a resolver for the type references in this type alias. - pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver { - // take the outer scope... - let r = self - .impl_block(db) - .map(|ib| ib.resolver(db)) - .unwrap_or_else(|| self.module(db).resolver(db)); - // ...and add generic params, if present - r.push_generic_params_scope(db, self.into()) - } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -1058,15 +965,6 @@ pub enum Container { } impl_froms!(Container: Trait, ImplBlock); -impl Container { - pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver { - match self { - Container::Trait(trait_) => trait_.resolver(db), - Container::ImplBlock(impl_block) => impl_block.resolver(db), - } - } -} - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum AssocItem { Function(Function), diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 8bfdda45e1..869879bdfa 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -11,6 +11,7 @@ use rustc_hash::FxHashSet; use crate::{ db::HirDatabase, diagnostics::{MissingFields, MissingOkInTailExpr}, + resolve::HasResolver, ty::{ApplicationTy, InferenceResult, Ty, TypeCtor}, Adt, DefWithBody, Function, HasBody, Name, Path, Resolver, }; diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index 54ed03642a..f1bf2ee9d1 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs @@ -2,8 +2,8 @@ use std::sync::Arc; use crate::{ - db::{DefDatabase, HirDatabase}, - Adt, Const, Container, Enum, EnumVariant, Function, ImplBlock, Struct, Trait, TypeAlias, Union, + db::DefDatabase, Adt, Const, Container, Enum, EnumVariant, Function, ImplBlock, Struct, Trait, + TypeAlias, Union, }; pub use hir_def::generics::{GenericParam, GenericParams, WherePredicate}; @@ -31,20 +31,6 @@ impl_froms!( Const ); -impl GenericDef { - pub(crate) fn resolver(&self, db: &impl HirDatabase) -> crate::Resolver { - match self { - GenericDef::Function(inner) => inner.resolver(db), - GenericDef::Adt(adt) => adt.resolver(db), - GenericDef::Trait(inner) => inner.resolver(db), - GenericDef::TypeAlias(inner) => inner.resolver(db), - GenericDef::ImplBlock(inner) => inner.resolver(db), - GenericDef::EnumVariant(inner) => inner.parent_enum(db).resolver(db), - GenericDef::Const(inner) => inner.resolver(db), - } - } -} - impl From for GenericDef { fn from(c: Container) -> Self { match c { diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index 492d964a43..964a3da8c0 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs @@ -5,7 +5,7 @@ use ra_syntax::ast::{self}; use crate::{ db::{AstDatabase, DefDatabase, HirDatabase}, - resolve::Resolver, + resolve::HasResolver, ty::Ty, AssocItem, Crate, HasSource, ImplBlock, Module, Source, TraitRef, }; @@ -50,12 +50,4 @@ impl ImplBlock { pub fn krate(&self, db: &impl DefDatabase) -> Crate { Crate { crate_id: self.module(db).id.krate } } - - pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver { - let r = self.module(db).resolver(db); - // add generic params, if present - let r = r.push_generic_params_scope(db, self.into()); - let r = r.push_impl_block_scope(self); - r - } } diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index e5e768be90..b8e1b4dad7 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs @@ -15,8 +15,8 @@ use crate::{ db::{DefDatabase, HirDatabase}, expr::{ExprScopes, PatId, ScopeId}, generics::{GenericParams, HasGenericParams}, - Adt, Const, DefWithBody, Enum, EnumVariant, Function, GenericDef, ImplBlock, Local, MacroDef, - ModuleDef, PerNs, Static, Struct, Trait, TypeAlias, + Adt, Const, Container, DefWithBody, Enum, EnumVariant, Function, GenericDef, ImplBlock, Local, + MacroDef, Module, ModuleDef, PerNs, Static, Struct, Trait, TypeAlias, Union, }; #[derive(Debug, Clone, Default)] @@ -486,3 +486,130 @@ impl Scope { } } } + +pub(crate) trait HasResolver { + /// Builds a resolver for type references inside this def. + fn resolver(self, db: &impl DefDatabase) -> Resolver; +} + +impl HasResolver for Module { + fn resolver(self, db: &impl DefDatabase) -> Resolver { + let def_map = db.crate_def_map(self.id.krate); + Resolver::default().push_module_scope(def_map, self.id.module_id) + } +} + +impl HasResolver for Trait { + fn resolver(self, db: &impl DefDatabase) -> Resolver { + self.module(db).resolver(db).push_generic_params_scope(db, self.into()) + } +} + +impl HasResolver for Struct { + fn resolver(self, db: &impl DefDatabase) -> Resolver { + self.module(db) + .resolver(db) + .push_generic_params_scope(db, self.into()) + .push_scope(Scope::AdtScope(self.into())) + } +} + +impl HasResolver for Union { + fn resolver(self, db: &impl DefDatabase) -> Resolver { + self.module(db) + .resolver(db) + .push_generic_params_scope(db, self.into()) + .push_scope(Scope::AdtScope(self.into())) + } +} + +impl HasResolver for Enum { + fn resolver(self, db: &impl DefDatabase) -> Resolver { + self.module(db) + .resolver(db) + .push_generic_params_scope(db, self.into()) + .push_scope(Scope::AdtScope(self.into())) + } +} + +impl HasResolver for Adt { + fn resolver(self, db: &impl DefDatabase) -> Resolver { + match self { + Adt::Struct(it) => it.resolver(db), + Adt::Union(it) => it.resolver(db), + Adt::Enum(it) => it.resolver(db), + } + } +} + +impl HasResolver for Function { + fn resolver(self, db: &impl DefDatabase) -> Resolver { + self.container(db) + .map(|c| c.resolver(db)) + .unwrap_or_else(|| self.module(db).resolver(db)) + .push_generic_params_scope(db, self.into()) + } +} + +impl HasResolver for DefWithBody { + fn resolver(self, db: &impl DefDatabase) -> Resolver { + match self { + DefWithBody::Const(c) => c.resolver(db), + DefWithBody::Function(f) => f.resolver(db), + DefWithBody::Static(s) => s.resolver(db), + } + } +} + +impl HasResolver for Const { + fn resolver(self, db: &impl DefDatabase) -> Resolver { + self.container(db).map(|c| c.resolver(db)).unwrap_or_else(|| self.module(db).resolver(db)) + } +} + +impl HasResolver for Static { + fn resolver(self, db: &impl DefDatabase) -> Resolver { + self.module(db).resolver(db) + } +} + +impl HasResolver for TypeAlias { + fn resolver(self, db: &impl DefDatabase) -> Resolver { + self.container(db) + .map(|ib| ib.resolver(db)) + .unwrap_or_else(|| self.module(db).resolver(db)) + .push_generic_params_scope(db, self.into()) + } +} + +impl HasResolver for Container { + fn resolver(self, db: &impl DefDatabase) -> Resolver { + match self { + Container::Trait(trait_) => trait_.resolver(db), + Container::ImplBlock(impl_block) => impl_block.resolver(db), + } + } +} + +impl HasResolver for GenericDef { + fn resolver(self, db: &impl DefDatabase) -> crate::Resolver { + match self { + GenericDef::Function(inner) => inner.resolver(db), + GenericDef::Adt(adt) => adt.resolver(db), + GenericDef::Trait(inner) => inner.resolver(db), + GenericDef::TypeAlias(inner) => inner.resolver(db), + GenericDef::ImplBlock(inner) => inner.resolver(db), + GenericDef::EnumVariant(inner) => inner.parent_enum(db).resolver(db), + GenericDef::Const(inner) => inner.resolver(db), + } + } +} + +impl HasResolver for ImplBlock { + fn resolver(self, db: &impl DefDatabase) -> Resolver { + self.module(db) + .resolver(db) + .push_generic_params_scope(db, self.into()) + .push_impl_block_scope(self) + } +} diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index fd9994098b..727310f066 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -23,7 +23,7 @@ use crate::{ db::HirDatabase, expr::{self, BodySourceMap, ExprScopes, ScopeId}, ids::LocationCtx, - resolve::{ScopeDef, TypeNs, ValueNs}, + resolve::{HasResolver, ScopeDef, TypeNs, ValueNs}, ty::method_resolution::{self, implements_trait}, AssocItem, Const, DefWithBody, Either, Enum, FromSource, Function, GenericParam, HasBody, HirFileId, Local, MacroDef, Module, Name, Path, Resolver, Static, Struct, Ty, diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 092bc3a3f2..7f9e81d649 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -40,7 +40,7 @@ use crate::{ code_model::TypeAlias, db::HirDatabase, expr::{BindingAnnotation, Body, ExprId, PatId}, - resolve::{Resolver, TypeNs}, + resolve::{HasResolver, Resolver, TypeNs}, ty::infer::diagnostics::InferenceDiagnostic, Adt, AssocItem, ConstData, DefWithBody, FloatTy, FnData, Function, HasBody, IntTy, Path, StructField, VariantDef, diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 91e60b5ab4..397ee7d5fc 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs @@ -22,7 +22,7 @@ use crate::{ db::HirDatabase, generics::HasGenericParams, generics::{GenericDef, WherePredicate}, - resolve::{Resolver, TypeNs}, + resolve::{HasResolver, Resolver, TypeNs}, ty::{ primitive::{FloatTy, IntTy, Uncertain}, Adt, diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs index 8c57c907d9..d5739b58a6 100644 --- a/crates/ra_ide_api/src/completion/complete_scope.rs +++ b/crates/ra_ide_api/src/completion/complete_scope.rs @@ -304,6 +304,13 @@ mod tests { ), @r###" [ + CompletionItem { + label: "Self", + source_range: [54; 54), + delete: [54; 54), + insert: "Self", + kind: TypeParam, + }, CompletionItem { label: "T", source_range: [54; 54), From 1cead415100c35097d5ea68cf58b9485fe306dc2 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 22:00:57 +0300 Subject: [PATCH 21/24] Simplify --- crates/ra_hir/src/code_model.rs | 17 +++++++------- crates/ra_hir/src/resolve.rs | 39 +++++---------------------------- 2 files changed, 15 insertions(+), 41 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index c5539e0764..a132d128b5 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -432,15 +432,16 @@ impl Adt { } } + pub fn module(self, db: &impl DefDatabase) -> Module { + match self { + Adt::Struct(s) => s.module(db), + Adt::Union(s) => s.module(db), + Adt::Enum(e) => e.module(db), + } + } + pub fn krate(self, db: &impl HirDatabase) -> Option { - Some( - match self { - Adt::Struct(s) => s.module(db), - Adt::Union(s) => s.module(db), - Adt::Enum(e) => e.module(db), - } - .krate(), - ) + Some(self.module(db).krate()) } } diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index b8e1b4dad7..eca8e05969 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs @@ -16,7 +16,7 @@ use crate::{ expr::{ExprScopes, PatId, ScopeId}, generics::{GenericParams, HasGenericParams}, Adt, Const, Container, DefWithBody, Enum, EnumVariant, Function, GenericDef, ImplBlock, Local, - MacroDef, Module, ModuleDef, PerNs, Static, Struct, Trait, TypeAlias, Union, + MacroDef, Module, ModuleDef, PerNs, Static, Struct, Trait, TypeAlias, }; #[derive(Debug, Clone, Default)] @@ -505,40 +505,13 @@ impl HasResolver for Trait { } } -impl HasResolver for Struct { +impl> HasResolver for T { fn resolver(self, db: &impl DefDatabase) -> Resolver { - self.module(db) + let def = self.into(); + def.module(db) .resolver(db) - .push_generic_params_scope(db, self.into()) - .push_scope(Scope::AdtScope(self.into())) - } -} - -impl HasResolver for Union { - fn resolver(self, db: &impl DefDatabase) -> Resolver { - self.module(db) - .resolver(db) - .push_generic_params_scope(db, self.into()) - .push_scope(Scope::AdtScope(self.into())) - } -} - -impl HasResolver for Enum { - fn resolver(self, db: &impl DefDatabase) -> Resolver { - self.module(db) - .resolver(db) - .push_generic_params_scope(db, self.into()) - .push_scope(Scope::AdtScope(self.into())) - } -} - -impl HasResolver for Adt { - fn resolver(self, db: &impl DefDatabase) -> Resolver { - match self { - Adt::Struct(it) => it.resolver(db), - Adt::Union(it) => it.resolver(db), - Adt::Enum(it) => it.resolver(db), - } + .push_generic_params_scope(db, def.into()) + .push_scope(Scope::AdtScope(def)) } } From 63f327be67a8e6e0786cc089fba5f9b3f53c5bd6 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 22:03:09 +0300 Subject: [PATCH 22/24] Alternative quite tests alias --- .cargo/config | 1 + 1 file changed, 1 insertion(+) diff --git a/.cargo/config b/.cargo/config index 9a04b9462a..560ab30752 100644 --- a/.cargo/config +++ b/.cargo/config @@ -2,3 +2,4 @@ xtask = "run --package xtask --bin xtask --" install-ra = "run --package xtask --bin xtask -- install" # for backwards compat tq = "test -- -q" +qt = "tq" From c079d9b63b995c37f0de500e4232a8303fc8a291 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Wed, 20 Nov 2019 20:30:41 +0100 Subject: [PATCH 23/24] Add rust-analyzer-expand-macro function for Emacs --- docs/user/README.md | 2 +- editors/emacs/ra-emacs-lsp.el | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/docs/user/README.md b/docs/user/README.md index 1861c69abc..bfb1904492 100644 --- a/docs/user/README.md +++ b/docs/user/README.md @@ -127,7 +127,7 @@ Installation: [ra-emacs-lsp.el](https://github.com/rust-analyzer/rust-analyzer/blob/69ee5c9c5ef212f7911028c9ddf581559e6565c3/editors/emacs/ra-emacs-lsp.el) to load path and require it in `init.el` * run `lsp` in a rust buffer -* (Optionally) bind commands like `rust-analyzer-join-lines` or `rust-analyzer-extend-selection` to keys, and enable `rust-analyzer-inlay-hints-mode` to get inline type hints +* (Optionally) bind commands like `rust-analyzer-join-lines`, `rust-analyzer-extend-selection` and `rust-analyzer-expand-macro` to keys, and enable `rust-analyzer-inlay-hints-mode` to get inline type hints ## Vim and NeoVim diff --git a/editors/emacs/ra-emacs-lsp.el b/editors/emacs/ra-emacs-lsp.el index 79822c8ced..fafb9cbe73 100644 --- a/editors/emacs/ra-emacs-lsp.el +++ b/editors/emacs/ra-emacs-lsp.el @@ -16,6 +16,7 @@ ;; - implements joinLines (you need to bind rust-analyzer-join-lines to a key) ;; - implements selectionRanges (either bind lsp-extend-selection to a key, or use expand-region) ;; - provides rust-analyzer-inlay-hints-mode for inline type hints +;; - provides rust-analyzer-expand-macro to expand macros ;; What's missing: ;; - file system changes in apply-source-change @@ -247,5 +248,32 @@ (remove-hook 'after-change-functions #'rust-analyzer--inlay-hints-change-handler t)))) + +;; expand macros +(defun rust-analyzer-expand-macro () + "Expands the macro call at point recursively." + (interactive) + (when (eq 'rust-mode major-mode) + (let* ((workspace (lsp-find-workspace 'rust-analyzer (buffer-file-name))) + (params (list :textDocument (lsp--text-document-identifier) + :position (lsp--cur-position)))) + (when workspace + (let* ((response (with-lsp-workspace workspace + (lsp-send-request (lsp-make-request + "rust-analyzer/expandMacro" + params)))) + (result (when response (ht-get response "expansion")))) + (if result + (let ((buf (get-buffer-create (concat "*rust-analyzer macro expansion " (with-lsp-workspace workspace (lsp-workspace-root)) "*")))) + (with-current-buffer buf + (let ((inhibit-read-only t)) + (erase-buffer) + (insert result) + (setq buffer-read-only t) + (special-mode))) + (pop-to-buffer buf)) + (message "No macro found at point, or it could not be expanded"))))))) + + (provide 'ra-emacs-lsp) ;;; ra-emacs-lsp.el ends here From ad2b6cad48dc336011c9fb24ba87b318b796b916 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 20 Nov 2019 23:27:03 +0300 Subject: [PATCH 24/24] Remove npm.cmd I *think* this is more correct --- xtask/src/main.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 4b1f0c887d..c97bfec977 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -173,7 +173,7 @@ fn fix_path_for_mac() -> Result<()> { fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> { let npm_version = Cmd { unix: r"npm --version", - windows: r"cmd.exe /c npm.cmd --version", + windows: r"cmd.exe /c npm --version", work_dir: "./editors/code", } .run(); @@ -182,10 +182,10 @@ fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> { eprintln!("\nERROR: `npm --version` failed, `npm` is required to build the VS Code plugin") } - Cmd { unix: r"npm ci", windows: r"cmd.exe /c npm.cmd ci", work_dir: "./editors/code" }.run()?; + Cmd { unix: r"npm ci", windows: r"cmd.exe /c npm ci", work_dir: "./editors/code" }.run()?; Cmd { unix: r"npm run package --scripts-prepend-node-path", - windows: r"cmd.exe /c npm.cmd run package", + windows: r"cmd.exe /c npm run package", work_dir: "./editors/code", } .run()?;