]> git.lizzy.rs Git - rust.git/commitdiff
support items that visible to the parent module
authorEkaterina Babshukova <ekaterina.babshukova@yandex.ru>
Wed, 16 Oct 2019 13:49:35 +0000 (16:49 +0300)
committerEkaterina Babshukova <ekaterina.babshukova@yandex.ru>
Tue, 22 Oct 2019 20:47:31 +0000 (23:47 +0300)
crates/ra_ide_api/src/references.rs
crates/ra_ide_api/src/references/classify.rs
crates/ra_ide_api/src/references/search_scope.rs

index 3d647d2cbc4d14e5114df0cb244fc64fde1b2e32..aadd52616bc103ae26799d0373b9a1cd3e3a0a23 100644 (file)
@@ -270,9 +270,8 @@ fn f() {
         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 @@ pub struct Foo {
         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()
index ac9cf34eb0c79fb564caeb9984dd06a4b1b3d9af..3beab9861efe0f71fb906fb607116ff20a53194e 100644 (file)
@@ -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 })
         }
index d2c966b4f3a632341975e4f65249da7106e70741..8495a92a514910100e75ae9bb892fa8054bdd528 100644 (file)
@@ -25,14 +25,53 @@ pub(crate) fn search_scope(&self, db: &RootDatabase) -> HashSet<(FileId, Option<
         }
 
         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::<HashSet<_>>(),
+                            );
+                        }
+                    }
+                    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::<HashSet<_>>();
 
-            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 @@ pub(crate) fn search_scope(&self, db: &RootDatabase) -> HashSet<(FileId, Option<
 
                 return files;
             }
-            // FIXME: "pub(super)", "pub(in path)"
         }
 
         let range = match module_src.ast {