]> git.lizzy.rs Git - rust.git/commitdiff
Merge #948
authorbors[bot] <bors[bot]@users.noreply.github.com>
Thu, 7 Mar 2019 17:35:57 +0000 (17:35 +0000)
committerbors[bot] <bors[bot]@users.noreply.github.com>
Thu, 7 Mar 2019 17:35:57 +0000 (17:35 +0000)
948: Fix test_missing_module_code_action_in_json_project on Windows r=matklad a=vipentti

The test would fail on Windows due to the paths not being properly escaped for
JSON.

In addition adds extra braces around the fn main to actually introduce braces in
the file.

Co-authored-by: Ville Penttinen <villem.penttinen@gmail.com>
crates/ra_hir/src/source_binder.rs
crates/ra_ide_api/src/goto_definition.rs
crates/ra_ide_api/src/hover.rs
crates/ra_ide_api/src/navigation_target.rs
crates/ra_lsp_server/Cargo.toml
crates/ra_project_model/Cargo.toml

index ea20cd15a24c50ddfe3102764905c4490c417b1a..4a9921a85220304855ecbbd35baff63953d1b882 100644 (file)
@@ -205,19 +205,8 @@ pub fn resolver_for_position(db: &impl HirDatabase, position: FilePosition) -> R
                         // TODO const/static/array length
                         None
                     }
-                } else if let Some(module) = ast::Module::cast(node) {
-                    Some(module_from_declaration(db, file_id, module)?.resolver(db))
-                } else if let Some(_) = ast::SourceFile::cast(node) {
-                    Some(module_from_source(db, file_id.into(), None)?.resolver(db))
-                } else if let Some(s) = ast::StructDef::cast(node) {
-                    let module = module_from_child_node(db, file_id, s.syntax())?;
-                    Some(struct_from_module(db, module, s).resolver(db))
-                } else if let Some(e) = ast::EnumDef::cast(node) {
-                    let module = module_from_child_node(db, file_id, e.syntax())?;
-                    Some(enum_from_module(db, module, e).resolver(db))
                 } else {
-                    // TODO add missing cases
-                    None
+                    try_get_resolver_for_node(db, file_id, node)
                 }
             })
         })
@@ -236,20 +225,32 @@ pub fn resolver_for_node(db: &impl HirDatabase, file_id: FileId, node: &SyntaxNo
                     // TODO const/static/array length
                     None
                 }
-            } else if let Some(module) = ast::Module::cast(node) {
-                Some(module_from_declaration(db, file_id, module)?.resolver(db))
-            } else if let Some(_) = ast::SourceFile::cast(node) {
-                Some(module_from_source(db, file_id.into(), None)?.resolver(db))
-            } else if let Some(s) = ast::StructDef::cast(node) {
-                let module = module_from_child_node(db, file_id, s.syntax())?;
-                Some(struct_from_module(db, module, s).resolver(db))
-            } else if let Some(e) = ast::EnumDef::cast(node) {
-                let module = module_from_child_node(db, file_id, e.syntax())?;
-                Some(enum_from_module(db, module, e).resolver(db))
             } else {
-                // TODO add missing cases
-                None
+                try_get_resolver_for_node(db, file_id, node)
             }
         })
         .unwrap_or_default()
 }
+
+fn try_get_resolver_for_node(
+    db: &impl HirDatabase,
+    file_id: FileId,
+    node: &SyntaxNode,
+) -> Option<Resolver> {
+    if let Some(module) = ast::Module::cast(node) {
+        Some(module_from_declaration(db, file_id, module)?.resolver(db))
+    } else if let Some(_) = ast::SourceFile::cast(node) {
+        Some(module_from_source(db, file_id.into(), None)?.resolver(db))
+    } else if let Some(s) = ast::StructDef::cast(node) {
+        let module = module_from_child_node(db, file_id, s.syntax())?;
+        Some(struct_from_module(db, module, s).resolver(db))
+    } else if let Some(e) = ast::EnumDef::cast(node) {
+        let module = module_from_child_node(db, file_id, e.syntax())?;
+        Some(enum_from_module(db, module, e).resolver(db))
+    } else if let Some(f) = ast::FnDef::cast(node) {
+        function_from_source(db, file_id, f).map(|f| f.resolver(db))
+    } else {
+        // TODO add missing cases
+        None
+    }
+}
index dd5f9f31c9afc77e385ef752145d4e4bff309bd3..d4e10b69ca72d469ba2b5740a788a86f9316ee38 100644 (file)
@@ -121,8 +121,12 @@ pub(crate) fn reference_definition(
             Some(Resolution::GenericParam(..)) => {
                 // TODO: go to the generic param def
             }
-            Some(Resolution::SelfType(_impl_block)) => {
-                // TODO: go to the implemented type
+            Some(Resolution::SelfType(impl_block)) => {
+                let ty = impl_block.target_ty(db);
+
+                if let hir::Ty::Adt { def_id, .. } = ty {
+                    return Exact(NavigationTarget::from_adt_def(db, def_id));
+                }
             }
             None => {
                 // If we failed to resolve then check associated items
@@ -337,6 +341,94 @@ fn bar() -> Foo {
             "spam NAMED_FIELD_DEF FileId(1) [17; 26) [17; 21)",
         );
     }
+    #[test]
+    fn goto_definition_on_self() {
+        check_goto(
+            "
+            //- /lib.rs
+            struct Foo;
+            impl Foo {
+                pub fn new() -> Self {
+                    Self<|> {}
+                }
+            }
+            ",
+            "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)",
+        );
+
+        check_goto(
+            "
+            //- /lib.rs
+            struct Foo;
+            impl Foo {
+                pub fn new() -> Self<|> {
+                    Self {}
+                }
+            }
+            ",
+            "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)",
+        );
+
+        check_goto(
+            "
+            //- /lib.rs
+            enum Foo { A }
+            impl Foo {
+                pub fn new() -> Self<|> {
+                    Foo::A
+                }
+            }
+            ",
+            "Foo ENUM_DEF FileId(1) [0; 14) [5; 8)",
+        );
+
+        check_goto(
+            "
+            //- /lib.rs
+            enum Foo { A }
+            impl Foo {
+                pub fn thing(a: &Self<|>) {
+                }
+            }
+            ",
+            "Foo ENUM_DEF FileId(1) [0; 14) [5; 8)",
+        );
+    }
+
+    #[test]
+    fn goto_definition_on_self_in_trait_impl() {
+        check_goto(
+            "
+            //- /lib.rs
+            struct Foo;
+            trait Make {
+                fn new() -> Self;
+            }
+            impl Make for Foo {
+                fn new() -> Self {
+                    Self<|> {}
+                }
+            }
+            ",
+            "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)",
+        );
+
+        check_goto(
+            "
+            //- /lib.rs
+            struct Foo;
+            trait Make {
+                fn new() -> Self;
+            }
+            impl Make for Foo {
+                fn new() -> Self<|> {
+                    Self{}
+                }
+            }
+            ",
+            "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)",
+        );
+    }
 
     #[test]
     fn goto_definition_works_when_used_on_definition_name_itself() {
index 638c24e3198434ab1fd38bba3c277a12779abe9f..f14001e849c7257409828f7a6ed18aaeb8af2977 100644 (file)
@@ -557,4 +557,62 @@ fn main() {
         assert_eq!(trim_markup_opt(hover.info.first()), Some("const C: u32"));
         assert_eq!(hover.info.is_exact(), true);
     }
+
+    #[test]
+    fn test_hover_self() {
+        let (analysis, position) = single_file_with_position(
+            "
+            struct Thing { x: u32 };
+            impl Thing {
+                fn new() -> Self {
+                    Self<|> { x: 0 }
+                }
+            }
+        ",
+        );
+        let hover = analysis.hover(position).unwrap().unwrap();
+        assert_eq!(trim_markup_opt(hover.info.first()), Some("struct Thing"));
+        assert_eq!(hover.info.is_exact(), true);
+
+        let (analysis, position) = single_file_with_position(
+            "
+            struct Thing { x: u32 };
+            impl Thing {
+                fn new() -> Self<|> {
+                    Self { x: 0 }
+                }
+            }
+            ",
+        );
+        let hover = analysis.hover(position).unwrap().unwrap();
+        assert_eq!(trim_markup_opt(hover.info.first()), Some("struct Thing"));
+        assert_eq!(hover.info.is_exact(), true);
+
+        let (analysis, position) = single_file_with_position(
+            "
+            enum Thing { A };
+            impl Thing {
+                pub fn new() -> Self<|> {
+                    Thing::A
+                }
+            }
+            ",
+        );
+        let hover = analysis.hover(position).unwrap().unwrap();
+        assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing"));
+        assert_eq!(hover.info.is_exact(), true);
+
+        let (analysis, position) = single_file_with_position(
+            "
+            enum Thing { A };
+            impl Thing {
+                pub fn thing(a: Self<|>) {
+                }
+            }
+            ",
+        );
+        let hover = analysis.hover(position).unwrap().unwrap();
+        assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing"));
+        assert_eq!(hover.info.is_exact(), true);
+    }
 }
index d806cb368d3cd20c4a115d8e19a7c4fe6acaf165..f6d7f31929f49b40489482d4a830dc1cdae4b709 100644 (file)
@@ -126,6 +126,19 @@ pub(crate) fn from_field(db: &RootDatabase, field: hir::StructField) -> Navigati
         }
     }
 
+    pub(crate) fn from_adt_def(db: &RootDatabase, adt_def: hir::AdtDef) -> NavigationTarget {
+        match adt_def {
+            hir::AdtDef::Struct(s) => {
+                let (file_id, node) = s.source(db);
+                NavigationTarget::from_named(file_id.original_file(db), &*node)
+            }
+            hir::AdtDef::Enum(s) => {
+                let (file_id, node) = s.source(db);
+                NavigationTarget::from_named(file_id.original_file(db), &*node)
+            }
+        }
+    }
+
     pub(crate) fn from_def(db: &RootDatabase, module_def: hir::ModuleDef) -> NavigationTarget {
         match module_def {
             hir::ModuleDef::Module(module) => NavigationTarget::from_module(db, module),
index a36e6b5ae0e56878b17af6a4981e19de642ae4bb..2b3890e0194b1786dbc00f27fc5062fc622c1005 100644 (file)
@@ -10,7 +10,7 @@ relative-path = "0.4.0"
 failure = "0.1.4"
 failure_derive = "0.1.4"
 serde_json = "1.0.34"
-serde = "1.0.83"
+serde = { version = "1.0.83", features = ["derive"] }
 crossbeam-channel = "0.3.5"
 flexi_logger = "0.11.0"
 log = "0.4.3"
index 487cdfaf11735ad722f66f3843028af911208e90..34d33531eb8355df912cf3e6ac52bf61393208d1 100644 (file)
@@ -17,7 +17,7 @@ cargo_metadata = "0.7.0"
 ra_arena = { path = "../ra_arena" }
 ra_db = { path = "../ra_db" }
 
-serde = "1.0.89"
+serde = { version = "1.0.89", features = ["derive"] }
 serde_json = "1.0.39"
 
 [dev-dependencies]