From b21829f7edd71fb14911fc6ba47fe715757e415f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 15 Nov 2019 21:28:00 +0300 Subject: Remove old impls infrastructure --- crates/ra_ide_api/src/change.rs | 4 +--- crates/ra_ide_api/src/references/classify.rs | 16 +++++++--------- 2 files changed, 8 insertions(+), 12 deletions(-) (limited to 'crates/ra_ide_api/src') diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs index 010b45141..5c9dec13e 100644 --- a/crates/ra_ide_api/src/change.rs +++ b/crates/ra_ide_api/src/change.rs @@ -271,7 +271,6 @@ impl RootDatabase { self.query(hir::db::AstIdMapQuery).sweep(sweep); self.query(hir::db::RawItemsWithSourceMapQuery).sweep(sweep); - self.query(hir::db::ImplsInModuleWithSourceMapQuery).sweep(sweep); self.query(hir::db::BodyWithSourceMapQuery).sweep(sweep); self.query(hir::db::ExprScopesQuery).sweep(sweep); @@ -314,8 +313,6 @@ impl RootDatabase { hir::db::RawItemsWithSourceMapQuery hir::db::RawItemsQuery hir::db::CrateDefMapQuery - hir::db::ImplsInModuleWithSourceMapQuery - hir::db::ImplsInModuleQuery hir::db::GenericParamsQuery hir::db::FnDataQuery hir::db::TypeAliasDataQuery @@ -340,6 +337,7 @@ impl RootDatabase { hir::db::TraitDatumQuery hir::db::StructDatumQuery hir::db::ImplDatumQuery + hir::db::ImplDataQuery hir::db::TraitSolveQuery ]; acc.sort_by_key(|it| std::cmp::Reverse(it.1)); diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs index 217f9951e..00690e449 100644 --- a/crates/ra_ide_api/src/references/classify.rs +++ b/crates/ra_ide_api/src/references/classify.rs @@ -114,8 +114,6 @@ pub(crate) fn classify_name_ref( file_id: FileId, name_ref: &ast::NameRef, ) -> Option { - use PathResolution::*; - let _p = profile("classify_name_ref"); let parent = name_ref.syntax().parent()?; @@ -163,26 +161,26 @@ pub(crate) fn classify_name_ref( let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; let resolved = analyzer.resolve_path(db, &path)?; match resolved { - Def(def) => Some(from_module_def(db, def, Some(container))), - AssocItem(item) => Some(from_assoc_item(db, item)), - Local(local) => { + PathResolution::Def(def) => Some(from_module_def(db, def, Some(container))), + PathResolution::AssocItem(item) => Some(from_assoc_item(db, item)), + PathResolution::Local(local) => { let container = local.module(db); let kind = NameKind::Local(local); Some(NameDefinition { kind, container, visibility: None }) } - GenericParam(par) => { + PathResolution::GenericParam(par) => { // FIXME: get generic param def let kind = NameKind::GenericParam(par); Some(NameDefinition { kind, container, visibility }) } - Macro(def) => { + PathResolution::Macro(def) => { let kind = NameKind::Macro(def); Some(NameDefinition { kind, container, visibility }) } - SelfType(impl_block) => { + PathResolution::SelfType(impl_block) => { let ty = impl_block.target_ty(db); let kind = NameKind::SelfType(ty); - let container = impl_block.module(); + let container = impl_block.module(db); Some(NameDefinition { kind, container, visibility }) } } -- cgit v1.2.3 From 4c90b7e2ecd03e739a3c92bbe5afd4c90fe2812d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 15 Nov 2019 23:24:56 +0300 Subject: Sourcify some things If we want to support macros properly, we need to get rid of those FileIds everywhere... --- crates/ra_ide_api/src/references/classify.rs | 2 +- crates/ra_ide_api/src/runnables.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'crates/ra_ide_api/src') diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs index 00690e449..b5e35e29f 100644 --- a/crates/ra_ide_api/src/references/classify.rs +++ b/crates/ra_ide_api/src/references/classify.rs @@ -144,8 +144,8 @@ pub(crate) fn classify_name_ref( } } - let ast = ModuleSource::from_child_node(db, file_id, &parent); let file_id = file_id.into(); + let ast = ModuleSource::from_child_node(db, Source::new(file_id, &parent)); // FIXME: find correct container and visibility for each case let container = Module::from_definition(db, Source { file_id, ast })?; let visibility = None; diff --git a/crates/ra_ide_api/src/runnables.rs b/crates/ra_ide_api/src/runnables.rs index 366ac8048..8039a5164 100644 --- a/crates/ra_ide_api/src/runnables.rs +++ b/crates/ra_ide_api/src/runnables.rs @@ -1,5 +1,6 @@ //! FIXME: write short doc here +use hir::Source; use itertools::Itertools; use ra_db::SourceDatabase; use ra_syntax::{ @@ -65,9 +66,8 @@ fn runnable_mod(db: &RootDatabase, file_id: FileId, module: ast::Module) -> Opti return None; } let range = module.syntax().text_range(); - let src = hir::ModuleSource::from_child_node(db, file_id, &module.syntax()); - let module = - hir::Module::from_definition(db, hir::Source { file_id: file_id.into(), ast: src })?; + let src = hir::ModuleSource::from_child_node(db, Source::new(file_id.into(), &module.syntax())); + let module = hir::Module::from_definition(db, Source::new(file_id.into(), src))?; let path = module.path_to_root(db).into_iter().rev().filter_map(|it| it.name(db)).join("::"); Some(Runnable { range, kind: RunnableKind::TestMod { path } }) -- cgit v1.2.3 From 60fd260e7fb8c88cb9037377dc75f901a54bbe20 Mon Sep 17 00:00:00 2001 From: kjeremy Date: Fri, 15 Nov 2019 16:20:00 -0500 Subject: Handle ast::MacroCall in classify_name and impl FromSource for MacroDef Fixes #2260 --- crates/ra_ide_api/src/references/classify.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'crates/ra_ide_api/src') diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs index b5e35e29f..0eeaa7f38 100644 --- a/crates/ra_ide_api/src/references/classify.rs +++ b/crates/ra_ide_api/src/references/classify.rs @@ -21,7 +21,6 @@ pub(crate) fn classify_name( let parent = name.syntax().parent()?; let file_id = file_id.into(); - // FIXME: add ast::MacroCall(it) match_ast! { match parent { ast::BindPat(it) => { @@ -104,6 +103,19 @@ pub(crate) fn classify_name( Some(from_module_def(db, def.into(), None)) } }, + ast::MacroCall(it) => { + let src = hir::Source { file_id, ast: 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, Source::new(file_id, module_src))?; + + Some(NameDefinition { + visibility: None, + container: module, + kind: NameKind::Macro(def), + }) + }, _ => None, } } -- cgit v1.2.3 From 06984ed1164d7607f89f9a6f4893dd05ec058a99 Mon Sep 17 00:00:00 2001 From: kjeremy Date: Fri, 15 Nov 2019 17:13:52 -0500 Subject: Add a test that uses classify_name --- crates/ra_ide_api/src/references.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'crates/ra_ide_api/src') diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs index 9cb9433e7..faa88d988 100644 --- a/crates/ra_ide_api/src/references.rs +++ b/crates/ra_ide_api/src/references.rs @@ -369,6 +369,21 @@ mod tests { assert_eq!(refs.len(), 2); } + #[test] + fn test_find_all_refs_macro_def() { + let code = r#" + #[macro_export] + macro_rules! m1<|> { () => (()) } + + fn foo() { + m1(); + m1(); + }"#; + + let refs = get_all_refs(code); + 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() -- cgit v1.2.3 From d898ecb8f2c19eb041bcb27c7ce9edd9d891f2c2 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 16 Nov 2019 00:56:51 +0300 Subject: Force passing Source when creating a SourceAnalyzer --- crates/ra_ide_api/src/call_info.rs | 6 +++++- crates/ra_ide_api/src/completion/completion_context.rs | 7 +++++-- crates/ra_ide_api/src/goto_type_definition.rs | 3 ++- crates/ra_ide_api/src/hover.rs | 3 ++- crates/ra_ide_api/src/inlay_hints.rs | 7 +------ crates/ra_ide_api/src/references/classify.rs | 3 ++- 6 files changed, 17 insertions(+), 12 deletions(-) (limited to 'crates/ra_ide_api/src') diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs index 3572825b5..41ee81511 100644 --- a/crates/ra_ide_api/src/call_info.rs +++ b/crates/ra_ide_api/src/call_info.rs @@ -19,7 +19,11 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option { //FIXME: apply subst diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs index 64cbc0f98..0906a4e1b 100644 --- a/crates/ra_ide_api/src/completion/completion_context.rs +++ b/crates/ra_ide_api/src/completion/completion_context.rs @@ -58,8 +58,11 @@ impl<'a> CompletionContext<'a> { ); let token = original_parse.tree().syntax().token_at_offset(position.offset).left_biased()?; - let analyzer = - hir::SourceAnalyzer::new(db, position.file_id, &token.parent(), Some(position.offset)); + let analyzer = hir::SourceAnalyzer::new( + db, + hir::Source::new(position.file_id.into(), &token.parent()), + Some(position.offset), + ); let mut ctx = CompletionContext { db, analyzer, diff --git a/crates/ra_ide_api/src/goto_type_definition.rs b/crates/ra_ide_api/src/goto_type_definition.rs index 71146591d..2327cb1e7 100644 --- a/crates/ra_ide_api/src/goto_type_definition.rs +++ b/crates/ra_ide_api/src/goto_type_definition.rs @@ -18,7 +18,8 @@ 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, position.file_id, &node, None); + let analyzer = + hir::SourceAnalyzer::new(db, hir::Source::new(position.file_id.into(), &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 07d511fb3..92b4b1f79 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs @@ -230,7 +230,8 @@ pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option { .ancestors() .take_while(|it| it.text_range() == leaf_node.text_range()) .find(|it| ast::Expr::cast(it.clone()).is_some() || ast::Pat::cast(it.clone()).is_some())?; - let analyzer = hir::SourceAnalyzer::new(db, frange.file_id, &node, None); + let analyzer = + hir::SourceAnalyzer::new(db, hir::Source::new(frange.file_id.into(), &node), None); let ty = if let Some(ty) = ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e)) { ty diff --git a/crates/ra_ide_api/src/inlay_hints.rs b/crates/ra_ide_api/src/inlay_hints.rs index 2ff10b89a..0cd959848 100644 --- a/crates/ra_ide_api/src/inlay_hints.rs +++ b/crates/ra_ide_api/src/inlay_hints.rs @@ -32,6 +32,7 @@ fn get_inlay_hints( file_id: FileId, node: &SyntaxNode, ) -> Option> { + let analyzer = SourceAnalyzer::new(db, hir::Source::new(file_id.into(), node), None); match_ast! { match node { ast::LetStmt(it) => { @@ -39,11 +40,9 @@ fn get_inlay_hints( return None; } let pat = it.pat()?; - let analyzer = SourceAnalyzer::new(db, file_id, it.syntax(), None); Some(get_pat_type_hints(db, &analyzer, pat, false)) }, ast::LambdaExpr(it) => { - let analyzer = SourceAnalyzer::new(db, file_id, it.syntax(), None); it.param_list().map(|param_list| { param_list .params() @@ -56,21 +55,17 @@ fn get_inlay_hints( }, ast::ForExpr(it) => { let pat = it.pat()?; - let analyzer = SourceAnalyzer::new(db, file_id, it.syntax(), None); Some(get_pat_type_hints(db, &analyzer, pat, false)) }, ast::IfExpr(it) => { let pat = it.condition()?.pat()?; - let analyzer = SourceAnalyzer::new(db, file_id, it.syntax(), None); Some(get_pat_type_hints(db, &analyzer, pat, true)) }, ast::WhileExpr(it) => { let pat = it.condition()?.pat()?; - let analyzer = SourceAnalyzer::new(db, file_id, it.syntax(), None); Some(get_pat_type_hints(db, &analyzer, pat, true)) }, ast::MatchArmList(it) => { - let analyzer = SourceAnalyzer::new(db, file_id, it.syntax(), None); Some( it .arms() diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs index b5e35e29f..0228c634d 100644 --- a/crates/ra_ide_api/src/references/classify.rs +++ b/crates/ra_ide_api/src/references/classify.rs @@ -117,7 +117,8 @@ pub(crate) fn classify_name_ref( let _p = profile("classify_name_ref"); let parent = name_ref.syntax().parent()?; - let analyzer = SourceAnalyzer::new(db, file_id, name_ref.syntax(), None); + let analyzer = + SourceAnalyzer::new(db, hir::Source::new(file_id.into(), name_ref.syntax()), None); if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { tested_by!(goto_definition_works_for_methods); -- cgit v1.2.3 From 272af56a5c5a0e89fc3c2db41e125f0f16df0d0c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 16 Nov 2019 13:33:25 +0300 Subject: Sourcify classify_name_ref --- crates/ra_ide_api/src/goto_definition.rs | 11 ++++++----- crates/ra_ide_api/src/hover.rs | 5 +++-- crates/ra_ide_api/src/references.rs | 5 +++-- crates/ra_ide_api/src/references/classify.rs | 17 +++++++---------- crates/ra_ide_api/src/syntax_highlighting.rs | 5 +++-- 5 files changed, 22 insertions(+), 21 deletions(-) (limited to 'crates/ra_ide_api/src') diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 6c8387f6c..5b7fb3c15 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -1,5 +1,6 @@ //! FIXME: write short doc here +use hir::Source; use ra_db::{FileId, SourceDatabase}; use ra_syntax::{ algo::find_node_at_offset, @@ -21,7 +22,8 @@ pub(crate) fn goto_definition( let parse = db.parse(position.file_id); let syntax = parse.tree().syntax().clone(); if let Some(name_ref) = find_node_at_offset::(&syntax, position.offset) { - let navs = reference_definition(db, position.file_id, &name_ref).to_vec(); + let navs = + reference_definition(db, Source::new(position.file_id.into(), &name_ref)).to_vec(); return Some(RangeInfo::new(name_ref.syntax().text_range(), navs.to_vec())); } if let Some(name) = find_node_at_offset::(&syntax, position.offset) { @@ -49,12 +51,11 @@ impl ReferenceResult { pub(crate) fn reference_definition( db: &RootDatabase, - file_id: FileId, - name_ref: &ast::NameRef, + name_ref: Source<&ast::NameRef>, ) -> ReferenceResult { use self::ReferenceResult::*; - let name_kind = classify_name_ref(db, file_id, &name_ref).map(|d| d.kind); + let name_kind = classify_name_ref(db, name_ref).map(|d| d.kind); match name_kind { Some(Macro(mac)) => return Exact(mac.to_nav(db)), Some(Field(field)) => return Exact(field.to_nav(db)), @@ -76,7 +77,7 @@ pub(crate) fn reference_definition( }; // Fallback index based approach: - let navs = crate::symbol_index::index_resolve(db, name_ref) + let navs = crate::symbol_index::index_resolve(db, name_ref.ast) .into_iter() .map(|s| s.to_nav(db)) .collect(); diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index 92b4b1f79..cc25f4c37 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs @@ -1,6 +1,6 @@ //! FIXME: write short doc here -use hir::{Adt, HasSource, HirDisplay}; +use hir::{Adt, HasSource, HirDisplay, Source}; use ra_db::SourceDatabase; use ra_syntax::{ algo::{ancestors_at_offset, find_covering_element, find_node_at_offset}, @@ -171,7 +171,8 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option(file.syntax(), position.offset) { let mut no_fallback = false; - if let Some(name_kind) = classify_name_ref(db, position.file_id, &name_ref).map(|d| d.kind) + if let Some(name_kind) = + classify_name_ref(db, Source::new(position.file_id.into(), &name_ref)).map(|d| d.kind) { res.extend(hover_text_from_name_kind(db, name_kind, &mut no_fallback)) } diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs index faa88d988..1af7e8a9f 100644 --- a/crates/ra_ide_api/src/references.rs +++ b/crates/ra_ide_api/src/references.rs @@ -14,6 +14,7 @@ mod name_definition; mod rename; mod search_scope; +use hir::Source; use once_cell::unsync::Lazy; use ra_db::{SourceDatabase, SourceDatabaseExt}; use ra_prof::profile; @@ -114,7 +115,7 @@ fn find_name<'a>( return Some(RangeInfo::new(range, (name.text().to_string(), def))); } let name_ref = find_node_at_offset::(&syntax, position.offset)?; - let def = classify_name_ref(db, position.file_id, &name_ref)?; + let def = classify_name_ref(db, Source::new(position.file_id.into(), &name_ref))?; let range = name_ref.syntax().text_range(); Some(RangeInfo::new(range, (name_ref.text().to_string(), def))) } @@ -146,7 +147,7 @@ fn process_definition( continue; } } - if let Some(d) = classify_name_ref(db, file_id, &name_ref) { + if let Some(d) = classify_name_ref(db, Source::new(file_id.into(), &name_ref)) { if d == def { refs.push(FileRange { file_id, range }); } diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs index f12b58cb9..5ca9da15e 100644 --- a/crates/ra_ide_api/src/references/classify.rs +++ b/crates/ra_ide_api/src/references/classify.rs @@ -123,14 +123,12 @@ pub(crate) fn classify_name( pub(crate) fn classify_name_ref( db: &RootDatabase, - file_id: FileId, - name_ref: &ast::NameRef, + name_ref: Source<&ast::NameRef>, ) -> Option { let _p = profile("classify_name_ref"); - let parent = name_ref.syntax().parent()?; - let analyzer = - SourceAnalyzer::new(db, hir::Source::new(file_id.into(), name_ref.syntax()), None); + let parent = name_ref.ast.syntax().parent()?; + let analyzer = SourceAnalyzer::new(db, name_ref.map(|it| it.syntax()), None); if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { tested_by!(goto_definition_works_for_methods); @@ -150,17 +148,16 @@ 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); + let hir_path = Path::from_name_ref(name_ref.ast); let hir_name = hir_path.as_ident()?; let field = variant_def.field(db, hir_name)?; return Some(from_struct_field(db, field)); } } - let file_id = file_id.into(); - let ast = ModuleSource::from_child_node(db, Source::new(file_id, &parent)); + let ast = ModuleSource::from_child_node(db, name_ref.with_ast(&parent)); // FIXME: find correct container and visibility for each case - let container = Module::from_definition(db, Source { file_id, ast })?; + let container = Module::from_definition(db, name_ref.with_ast(ast))?; let visibility = None; if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { @@ -171,7 +168,7 @@ pub(crate) fn classify_name_ref( } } - let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; + let path = name_ref.ast.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/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs index d53a759ee..584657ca2 100644 --- a/crates/ra_ide_api/src/syntax_highlighting.rs +++ b/crates/ra_ide_api/src/syntax_highlighting.rs @@ -2,7 +2,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; -use hir::{Mutability, Name}; +use hir::{Mutability, Name, Source}; use ra_db::SourceDatabase; use ra_prof::profile; use ra_syntax::{ast, AstNode, Direction, SyntaxElement, SyntaxKind, SyntaxKind::*, TextRange, T}; @@ -80,7 +80,8 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec Date: Sat, 16 Nov 2019 13:50:04 +0300 Subject: Source-ify name_definition --- crates/ra_ide_api/src/goto_definition.rs | 39 ++++++++++++++++---------------- 1 file changed, 19 insertions(+), 20 deletions(-) (limited to 'crates/ra_ide_api/src') diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 5b7fb3c15..821796e5f 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -1,7 +1,7 @@ //! FIXME: write short doc here use hir::Source; -use ra_db::{FileId, SourceDatabase}; +use ra_db::SourceDatabase; use ra_syntax::{ algo::find_node_at_offset, ast::{self, DocCommentsOwner}, @@ -27,7 +27,7 @@ pub(crate) fn goto_definition( return Some(RangeInfo::new(name_ref.syntax().text_range(), navs.to_vec())); } if let Some(name) = find_node_at_offset::(&syntax, position.offset) { - let navs = name_definition(db, position.file_id, &name)?; + let navs = name_definition(db, Source::new(position.file_id.into(), &name))?; return Some(RangeInfo::new(name.syntax().text_range(), navs)); } None @@ -86,14 +86,13 @@ pub(crate) fn reference_definition( pub(crate) fn name_definition( db: &RootDatabase, - file_id: FileId, - name: &ast::Name, + name: Source<&ast::Name>, ) -> Option> { - let parent = name.syntax().parent()?; + let parent = name.ast.syntax().parent()?; if let Some(module) = ast::Module::cast(parent.clone()) { if module.has_semi() { - let src = hir::Source { file_id: file_id.into(), ast: module }; + let src = name.with_ast(module); if let Some(child_module) = hir::Module::from_declaration(db, src) { let nav = child_module.to_nav(db); return Some(vec![nav]); @@ -101,20 +100,20 @@ pub(crate) fn name_definition( } } - if let Some(nav) = named_target(db, file_id, &parent) { + if let Some(nav) = named_target(db, name.with_ast(&parent)) { return Some(vec![nav]); } None } -fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option { +fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option { match_ast! { - match node { + match (node.ast) { ast::StructDef(it) => { Some(NavigationTarget::from_named( db, - file_id.into(), + node.file_id, &it, it.doc_comment_text(), it.short_label(), @@ -123,7 +122,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option ast::EnumDef(it) => { Some(NavigationTarget::from_named( db, - file_id.into(), + node.file_id, &it, it.doc_comment_text(), it.short_label(), @@ -132,7 +131,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option ast::EnumVariant(it) => { Some(NavigationTarget::from_named( db, - file_id.into(), + node.file_id, &it, it.doc_comment_text(), it.short_label(), @@ -141,7 +140,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option ast::FnDef(it) => { Some(NavigationTarget::from_named( db, - file_id.into(), + node.file_id, &it, it.doc_comment_text(), it.short_label(), @@ -150,7 +149,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option ast::TypeAliasDef(it) => { Some(NavigationTarget::from_named( db, - file_id.into(), + node.file_id, &it, it.doc_comment_text(), it.short_label(), @@ -159,7 +158,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option ast::ConstDef(it) => { Some(NavigationTarget::from_named( db, - file_id.into(), + node.file_id, &it, it.doc_comment_text(), it.short_label(), @@ -168,7 +167,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option ast::StaticDef(it) => { Some(NavigationTarget::from_named( db, - file_id.into(), + node.file_id, &it, it.doc_comment_text(), it.short_label(), @@ -177,7 +176,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option ast::TraitDef(it) => { Some(NavigationTarget::from_named( db, - file_id.into(), + node.file_id, &it, it.doc_comment_text(), it.short_label(), @@ -186,7 +185,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option ast::RecordFieldDef(it) => { Some(NavigationTarget::from_named( db, - file_id.into(), + node.file_id, &it, it.doc_comment_text(), it.short_label(), @@ -195,7 +194,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option ast::Module(it) => { Some(NavigationTarget::from_named( db, - file_id.into(), + node.file_id, &it, it.doc_comment_text(), it.short_label(), @@ -204,7 +203,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option ast::MacroCall(it) => { Some(NavigationTarget::from_named( db, - file_id.into(), + node.file_id, &it, it.doc_comment_text(), None, -- cgit v1.2.3 From 2eaa8c94a8a6b5cd86139c5e010ae95268b28658 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 16 Nov 2019 16:49:26 +0300 Subject: Goto definition works inside macros --- crates/ra_ide_api/src/goto_definition.rs | 50 +++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 10 deletions(-) (limited to 'crates/ra_ide_api/src') diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 821796e5f..4b1581499 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -1,11 +1,10 @@ //! FIXME: write short doc here -use hir::Source; -use ra_db::SourceDatabase; +use hir::{db::AstDatabase, Source}; use ra_syntax::{ algo::find_node_at_offset, ast::{self, DocCommentsOwner}, - match_ast, AstNode, SyntaxNode, + match_ast, AstNode, SyntaxNode, TextUnit, }; use crate::{ @@ -19,17 +18,29 @@ pub(crate) fn goto_definition( db: &RootDatabase, position: FilePosition, ) -> Option>> { - let parse = db.parse(position.file_id); - let syntax = parse.tree().syntax().clone(); - if let Some(name_ref) = find_node_at_offset::(&syntax, position.offset) { - let navs = - reference_definition(db, Source::new(position.file_id.into(), &name_ref)).to_vec(); + go(db, Source::new(position.file_id.into(), position.offset)) +} + +fn go(db: &RootDatabase, offset: Source) -> Option>> { + let syntax = db.parse_or_expand(offset.file_id)?; + + if let Some(name_ref) = find_node_at_offset::(&syntax, offset.ast) { + let navs = reference_definition(db, offset.with_ast(&name_ref)).to_vec(); return Some(RangeInfo::new(name_ref.syntax().text_range(), navs.to_vec())); } - if let Some(name) = find_node_at_offset::(&syntax, position.offset) { - let navs = name_definition(db, Source::new(position.file_id.into(), &name))?; + if let Some(name) = find_node_at_offset::(&syntax, offset.ast) { + let navs = name_definition(db, offset.with_ast(&name))?; return Some(RangeInfo::new(name.syntax().text_range(), navs)); } + if let Some(macro_call) = find_node_at_offset::(&syntax, offset.ast) { + let source_analyzer = + hir::SourceAnalyzer::new(db, offset.with_ast(macro_call.syntax()), None); + if let Some(exp) = source_analyzer.expand(db, ¯o_call) { + if let Some(offset) = exp.translate_offset(db, offset.ast) { + return go(db, Source::new(exp.file_id(), offset)); + } + } + } None } @@ -677,4 +688,23 @@ mod tests { "bar MODULE FileId(1) [0; 11) [4; 7)", ); } + + #[test] + fn goto_from_macro() { + check_goto( + " + //- /lib.rs + macro_rules! id { + ($($tt:tt)*) => { $($tt)* } + } + fn foo() {} + id! { + fn bar() { + fo<|>o(); + } + } + ", + "foo FN_DEF FileId(1) [52; 63) [55; 58)", + ); + } } -- cgit v1.2.3 From 42604c673d159edc1571732c6be1dc00a365b7be Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 16 Nov 2019 22:18:07 +0300 Subject: Better factoring of macro expansion machinery in goto def --- crates/ra_ide_api/src/goto_definition.rs | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'crates/ra_ide_api/src') diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 4b1581499..70baa294f 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -1,5 +1,7 @@ //! FIXME: write short doc here +use std::iter::successors; + use hir::{db::AstDatabase, Source}; use ra_syntax::{ algo::find_node_at_offset, @@ -18,10 +20,8 @@ pub(crate) fn goto_definition( db: &RootDatabase, position: FilePosition, ) -> Option>> { - go(db, Source::new(position.file_id.into(), position.offset)) -} + let offset = descend_into_macros(db, position); -fn go(db: &RootDatabase, offset: Source) -> Option>> { let syntax = db.parse_or_expand(offset.file_id)?; if let Some(name_ref) = find_node_at_offset::(&syntax, offset.ast) { @@ -32,16 +32,25 @@ fn go(db: &RootDatabase, offset: Source) -> Option(&syntax, offset.ast) { + None +} + +fn descend_into_macros(db: &RootDatabase, position: FilePosition) -> Source { + successors(Some(Source::new(position.file_id.into(), position.offset)), |offset| { + let syntax = db.parse_or_expand(offset.file_id)?; + let macro_call = find_node_at_offset::(&syntax, offset.ast)?; + let tt = macro_call.token_tree()?; + if !tt.syntax().text_range().contains(offset.ast) { + return None; + } let source_analyzer = hir::SourceAnalyzer::new(db, offset.with_ast(macro_call.syntax()), None); - if let Some(exp) = source_analyzer.expand(db, ¯o_call) { - if let Some(offset) = exp.translate_offset(db, offset.ast) { - return go(db, Source::new(exp.file_id(), offset)); - } - } - } - None + let exp = source_analyzer.expand(db, ¯o_call)?; + let next_offset = exp.translate_offset(db, offset.ast)?; + Some(Source::new(exp.file_id(), next_offset)) + }) + .last() + .unwrap() } #[derive(Debug)] -- cgit v1.2.3 From fd52d721e1ed9794048d63e546f43805d24d7ab8 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 17 Nov 2019 20:15:55 +0300 Subject: More correct expansion mapping We can't really map arbitrary ranges, we only can map tokens --- crates/ra_ide_api/src/goto_definition.rs | 48 +++++++++++++++++--------------- 1 file changed, 26 insertions(+), 22 deletions(-) (limited to 'crates/ra_ide_api/src') diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 70baa294f..b693a4c31 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -4,9 +4,8 @@ use std::iter::successors; use hir::{db::AstDatabase, Source}; use ra_syntax::{ - algo::find_node_at_offset, ast::{self, DocCommentsOwner}, - match_ast, AstNode, SyntaxNode, TextUnit, + match_ast, AstNode, SyntaxNode, SyntaxToken, }; use crate::{ @@ -20,37 +19,42 @@ pub(crate) fn goto_definition( db: &RootDatabase, position: FilePosition, ) -> Option>> { - let offset = descend_into_macros(db, position); + let token = descend_into_macros(db, position)?; - let syntax = db.parse_or_expand(offset.file_id)?; + let res = match_ast! { + match (token.ast.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()) + }, + ast::Name(name) => { + let navs = name_definition(db, token.with_ast(&name))?; + RangeInfo::new(name.syntax().text_range(), navs) - if let Some(name_ref) = find_node_at_offset::(&syntax, offset.ast) { - let navs = reference_definition(db, offset.with_ast(&name_ref)).to_vec(); - return Some(RangeInfo::new(name_ref.syntax().text_range(), navs.to_vec())); - } - if let Some(name) = find_node_at_offset::(&syntax, offset.ast) { - let navs = name_definition(db, offset.with_ast(&name))?; - return Some(RangeInfo::new(name.syntax().text_range(), navs)); - } - None + }, + _ => return None, + } + }; + + Some(res) } -fn descend_into_macros(db: &RootDatabase, position: FilePosition) -> Source { - successors(Some(Source::new(position.file_id.into(), position.offset)), |offset| { - let syntax = db.parse_or_expand(offset.file_id)?; - let macro_call = find_node_at_offset::(&syntax, offset.ast)?; +fn descend_into_macros(db: &RootDatabase, position: FilePosition) -> Option> { + let file = db.parse_or_expand(position.file_id.into())?; + let token = file.token_at_offset(position.offset).filter(|it| !it.kind().is_trivia()).next()?; + + successors(Some(Source::new(position.file_id.into(), token)), |token| { + let macro_call = token.ast.ancestors().find_map(ast::MacroCall::cast)?; let tt = macro_call.token_tree()?; - if !tt.syntax().text_range().contains(offset.ast) { + if !token.ast.text_range().is_subrange(&tt.syntax().text_range()) { return None; } let source_analyzer = - hir::SourceAnalyzer::new(db, offset.with_ast(macro_call.syntax()), None); + hir::SourceAnalyzer::new(db, token.with_ast(token.ast.parent()).as_ref(), None); let exp = source_analyzer.expand(db, ¯o_call)?; - let next_offset = exp.translate_offset(db, offset.ast)?; - Some(Source::new(exp.file_id(), next_offset)) + exp.map_token_down(db, token.as_ref()) }) .last() - .unwrap() } #[derive(Debug)] -- cgit v1.2.3