diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs index 3d647d2cbc4..aadd52616bc 100644 --- a/crates/ra_ide_api/src/references.rs +++ b/crates/ra_ide_api/src/references.rs @@ -270,9 +270,8 @@ mod tests { assert_eq!(refs.len(), 3); } - // `mod foo;` is not in the results because `foo` is an `ast::Name`. - // So, there are two references: the first one is a definition of the `foo` module, + // So, there are two references: the first one is a definition of the `foo` module, // which is the whole `foo.rs`, and the second one is in `use foo::Foo`. #[test] fn test_find_all_refs_decl_module() { @@ -297,6 +296,31 @@ mod tests { assert_eq!(refs.len(), 2); } + #[test] + fn test_find_all_refs_super_mod_vis() { + let code = r#" + //- /lib.rs + mod foo; + + //- /foo.rs + mod some; + use some::Foo; + + fn f() { + let i = Foo { n: 5 }; + } + + //- /foo/some.rs + pub(super) struct Foo<|> { + pub n: u32, + } + "#; + + let (analysis, pos) = analysis_and_position(code); + let refs = analysis.find_all_refs(pos).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).unwrap().unwrap() diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs index ac9cf34eb0c..3beab9861ef 100644 --- a/crates/ra_ide_api/src/references/classify.rs +++ b/crates/ra_ide_api/src/references/classify.rs @@ -152,6 +152,7 @@ pub(crate) fn classify_name_ref( AssocItem(item) => Some(from_assoc_item(db, item)), LocalBinding(Either::A(pat)) => from_pat(db, file_id, pat), LocalBinding(Either::B(par)) => { + // Not really supported let kind = NameKind::SelfParam(par); Some(NameDefinition { kind, container, visibility }) } diff --git a/crates/ra_ide_api/src/references/search_scope.rs b/crates/ra_ide_api/src/references/search_scope.rs index d2c966b4f3a..8495a92a514 100644 --- a/crates/ra_ide_api/src/references/search_scope.rs +++ b/crates/ra_ide_api/src/references/search_scope.rs @@ -25,14 +25,53 @@ impl NameDefinition { } if let Some(ref vis) = self.visibility { + let vis = vis.syntax().to_string(); + + // FIXME: add "pub(in path)" + + if vis.as_str() == "pub(super)" { + if let Some(parent_module) = self.container.parent(db) { + let mut files = HashSet::new(); + + let parent_src = parent_module.definition_source(db); + let file_id = parent_src.file_id.original_file(db); + + match parent_src.ast { + ModuleSource::Module(m) => { + let range = Some(m.syntax().text_range()); + files.insert((file_id, range)); + } + ModuleSource::SourceFile(_) => { + files.insert((file_id, None)); + files.extend( + parent_module + .children(db) + .map(|m| { + let src = m.definition_source(db); + (src.file_id.original_file(db), None) + }) + .collect::>(), + ); + } + } + return files; + } else { + let range = match module_src.ast { + ModuleSource::Module(m) => Some(m.syntax().text_range()), + ModuleSource::SourceFile(_) => None, + }; + return [(file_id, range)].iter().cloned().collect(); + } + } + let source_root_id = db.file_source_root(file_id); let source_root = db.source_root(source_root_id); let mut files = source_root.walk().map(|id| (id.into(), None)).collect::>(); - if vis.syntax().to_string().as_str() == "pub(crate)" { + if vis.as_str() == "pub(crate)" { return files; } - if vis.syntax().to_string().as_str() == "pub" { + if vis.as_str() == "pub" { let krate = self.container.krate(db).unwrap(); let crate_graph = db.crate_graph(); @@ -49,7 +88,6 @@ impl NameDefinition { return files; } - // FIXME: "pub(super)", "pub(in path)" } let range = match module_src.ast {