diff options
Diffstat (limited to 'crates/ra_ide/src/references')
-rw-r--r-- | crates/ra_ide/src/references/classify.rs | 29 | ||||
-rw-r--r-- | crates/ra_ide/src/references/name_definition.rs | 6 | ||||
-rw-r--r-- | crates/ra_ide/src/references/rename.rs | 54 | ||||
-rw-r--r-- | crates/ra_ide/src/references/search_scope.rs | 16 |
4 files changed, 80 insertions, 25 deletions
diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs index 5cea805ec..3483a7176 100644 --- a/crates/ra_ide/src/references/classify.rs +++ b/crates/ra_ide/src/references/classify.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! Functions that are used to classify an element from its definition or reference. | 1 | //! Functions that are used to classify an element from its definition or reference. |
2 | 2 | ||
3 | use hir::{FromSource, Module, ModuleSource, PathResolution, Source, SourceAnalyzer}; | 3 | use hir::{FromSource, InFile, Module, ModuleSource, PathResolution, SourceAnalyzer}; |
4 | use ra_prof::profile; | 4 | use ra_prof::profile; |
5 | use ra_syntax::{ast, match_ast, AstNode}; | 5 | use ra_syntax::{ast, match_ast, AstNode}; |
6 | use test_utils::tested_by; | 6 | use test_utils::tested_by; |
@@ -11,7 +11,7 @@ use super::{ | |||
11 | }; | 11 | }; |
12 | use crate::db::RootDatabase; | 12 | use crate::db::RootDatabase; |
13 | 13 | ||
14 | pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Option<NameDefinition> { | 14 | pub(crate) fn classify_name(db: &RootDatabase, name: InFile<&ast::Name>) -> Option<NameDefinition> { |
15 | let _p = profile("classify_name"); | 15 | let _p = profile("classify_name"); |
16 | let parent = name.value.syntax().parent()?; | 16 | let parent = name.value.syntax().parent()?; |
17 | 17 | ||
@@ -110,6 +110,15 @@ pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Opti | |||
110 | kind: NameKind::Macro(def), | 110 | kind: NameKind::Macro(def), |
111 | }) | 111 | }) |
112 | }, | 112 | }, |
113 | ast::TypeParam(it) => { | ||
114 | let src = name.with_value(it); | ||
115 | let def = hir::TypeParam::from_source(db, src)?; | ||
116 | Some(NameDefinition { | ||
117 | visibility: None, | ||
118 | container: def.module(db), | ||
119 | kind: NameKind::TypeParam(def), | ||
120 | }) | ||
121 | }, | ||
113 | _ => None, | 122 | _ => None, |
114 | } | 123 | } |
115 | } | 124 | } |
@@ -117,7 +126,7 @@ pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Opti | |||
117 | 126 | ||
118 | pub(crate) fn classify_name_ref( | 127 | pub(crate) fn classify_name_ref( |
119 | db: &RootDatabase, | 128 | db: &RootDatabase, |
120 | name_ref: Source<&ast::NameRef>, | 129 | name_ref: InFile<&ast::NameRef>, |
121 | ) -> Option<NameDefinition> { | 130 | ) -> Option<NameDefinition> { |
122 | let _p = profile("classify_name_ref"); | 131 | let _p = profile("classify_name_ref"); |
123 | 132 | ||
@@ -125,21 +134,22 @@ pub(crate) fn classify_name_ref( | |||
125 | let analyzer = SourceAnalyzer::new(db, name_ref.map(|it| it.syntax()), None); | 134 | let analyzer = SourceAnalyzer::new(db, name_ref.map(|it| it.syntax()), None); |
126 | 135 | ||
127 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { | 136 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { |
128 | tested_by!(goto_definition_works_for_methods); | 137 | tested_by!(goto_def_for_methods); |
129 | if let Some(func) = analyzer.resolve_method_call(&method_call) { | 138 | if let Some(func) = analyzer.resolve_method_call(&method_call) { |
130 | return Some(from_assoc_item(db, func.into())); | 139 | return Some(from_assoc_item(db, func.into())); |
131 | } | 140 | } |
132 | } | 141 | } |
133 | 142 | ||
134 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { | 143 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { |
135 | tested_by!(goto_definition_works_for_fields); | 144 | tested_by!(goto_def_for_fields); |
136 | if let Some(field) = analyzer.resolve_field(&field_expr) { | 145 | if let Some(field) = analyzer.resolve_field(&field_expr) { |
137 | return Some(from_struct_field(db, field)); | 146 | return Some(from_struct_field(db, field)); |
138 | } | 147 | } |
139 | } | 148 | } |
140 | 149 | ||
141 | if let Some(record_field) = ast::RecordField::cast(parent.clone()) { | 150 | if let Some(record_field) = ast::RecordField::cast(parent.clone()) { |
142 | tested_by!(goto_definition_works_for_record_fields); | 151 | tested_by!(goto_def_for_record_fields); |
152 | tested_by!(goto_def_for_field_init_shorthand); | ||
143 | if let Some(field_def) = analyzer.resolve_record_field(&record_field) { | 153 | if let Some(field_def) = analyzer.resolve_record_field(&record_field) { |
144 | return Some(from_struct_field(db, field_def)); | 154 | return Some(from_struct_field(db, field_def)); |
145 | } | 155 | } |
@@ -151,7 +161,7 @@ pub(crate) fn classify_name_ref( | |||
151 | let visibility = None; | 161 | let visibility = None; |
152 | 162 | ||
153 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { | 163 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { |
154 | tested_by!(goto_definition_works_for_macros); | 164 | tested_by!(goto_def_for_macros); |
155 | if let Some(macro_def) = analyzer.resolve_macro_call(db, name_ref.with_value(¯o_call)) { | 165 | if let Some(macro_def) = analyzer.resolve_macro_call(db, name_ref.with_value(¯o_call)) { |
156 | let kind = NameKind::Macro(macro_def); | 166 | let kind = NameKind::Macro(macro_def); |
157 | return Some(NameDefinition { kind, container, visibility }); | 167 | return Some(NameDefinition { kind, container, visibility }); |
@@ -168,9 +178,8 @@ pub(crate) fn classify_name_ref( | |||
168 | let kind = NameKind::Local(local); | 178 | let kind = NameKind::Local(local); |
169 | Some(NameDefinition { kind, container, visibility: None }) | 179 | Some(NameDefinition { kind, container, visibility: None }) |
170 | } | 180 | } |
171 | PathResolution::GenericParam(par) => { | 181 | PathResolution::TypeParam(par) => { |
172 | // FIXME: get generic param def | 182 | let kind = NameKind::TypeParam(par); |
173 | let kind = NameKind::GenericParam(par); | ||
174 | Some(NameDefinition { kind, container, visibility }) | 183 | Some(NameDefinition { kind, container, visibility }) |
175 | } | 184 | } |
176 | PathResolution::Macro(def) => { | 185 | PathResolution::Macro(def) => { |
diff --git a/crates/ra_ide/src/references/name_definition.rs b/crates/ra_ide/src/references/name_definition.rs index 10d3a2364..8c67c8863 100644 --- a/crates/ra_ide/src/references/name_definition.rs +++ b/crates/ra_ide/src/references/name_definition.rs | |||
@@ -4,8 +4,8 @@ | |||
4 | //! Note that the reference search is possible for not all of the classified items. | 4 | //! Note that the reference search is possible for not all of the classified items. |
5 | 5 | ||
6 | use hir::{ | 6 | use hir::{ |
7 | Adt, AssocItem, GenericParam, HasSource, ImplBlock, Local, MacroDef, Module, ModuleDef, | 7 | Adt, AssocItem, HasSource, ImplBlock, Local, MacroDef, Module, ModuleDef, StructField, |
8 | StructField, VariantDef, | 8 | TypeParam, VariantDef, |
9 | }; | 9 | }; |
10 | use ra_syntax::{ast, ast::VisibilityOwner}; | 10 | use ra_syntax::{ast, ast::VisibilityOwner}; |
11 | 11 | ||
@@ -19,7 +19,7 @@ pub enum NameKind { | |||
19 | Def(ModuleDef), | 19 | Def(ModuleDef), |
20 | SelfType(ImplBlock), | 20 | SelfType(ImplBlock), |
21 | Local(Local), | 21 | Local(Local), |
22 | GenericParam(GenericParam), | 22 | TypeParam(TypeParam), |
23 | } | 23 | } |
24 | 24 | ||
25 | #[derive(PartialEq, Eq)] | 25 | #[derive(PartialEq, Eq)] |
diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs index d58496049..b804d5f6d 100644 --- a/crates/ra_ide/src/references/rename.rs +++ b/crates/ra_ide/src/references/rename.rs | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | use hir::ModuleSource; | 3 | use hir::ModuleSource; |
4 | use ra_db::{RelativePath, RelativePathBuf, SourceDatabase, SourceDatabaseExt}; | 4 | use ra_db::{RelativePath, RelativePathBuf, SourceDatabase, SourceDatabaseExt}; |
5 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SyntaxNode}; | 5 | use ra_syntax::{algo::find_node_at_offset, ast, tokenize, AstNode, SyntaxKind, SyntaxNode}; |
6 | use ra_text_edit::TextEdit; | 6 | use ra_text_edit::TextEdit; |
7 | 7 | ||
8 | use crate::{ | 8 | use crate::{ |
@@ -17,6 +17,13 @@ pub(crate) fn rename( | |||
17 | position: FilePosition, | 17 | position: FilePosition, |
18 | new_name: &str, | 18 | new_name: &str, |
19 | ) -> Option<RangeInfo<SourceChange>> { | 19 | ) -> Option<RangeInfo<SourceChange>> { |
20 | let tokens = tokenize(new_name); | ||
21 | if tokens.len() != 1 | ||
22 | || (tokens[0].kind != SyntaxKind::IDENT && tokens[0].kind != SyntaxKind::UNDERSCORE) | ||
23 | { | ||
24 | return None; | ||
25 | } | ||
26 | |||
20 | let parse = db.parse(position.file_id); | 27 | let parse = db.parse(position.file_id); |
21 | if let Some((ast_name, ast_module)) = | 28 | if let Some((ast_name, ast_module)) = |
22 | find_name_and_module_at_offset(parse.tree().syntax(), position) | 29 | find_name_and_module_at_offset(parse.tree().syntax(), position) |
@@ -55,7 +62,7 @@ fn rename_mod( | |||
55 | ) -> Option<SourceChange> { | 62 | ) -> Option<SourceChange> { |
56 | let mut source_file_edits = Vec::new(); | 63 | let mut source_file_edits = Vec::new(); |
57 | let mut file_system_edits = Vec::new(); | 64 | let mut file_system_edits = Vec::new(); |
58 | let module_src = hir::Source { file_id: position.file_id.into(), value: ast_module.clone() }; | 65 | let module_src = hir::InFile { file_id: position.file_id.into(), value: ast_module.clone() }; |
59 | if let Some(module) = hir::Module::from_declaration(db, module_src) { | 66 | if let Some(module) = hir::Module::from_declaration(db, module_src) { |
60 | let src = module.definition_source(db); | 67 | let src = module.definition_source(db); |
61 | let file_id = src.file_id.original_file(db); | 68 | let file_id = src.file_id.original_file(db); |
@@ -124,6 +131,49 @@ mod tests { | |||
124 | }; | 131 | }; |
125 | 132 | ||
126 | #[test] | 133 | #[test] |
134 | fn test_rename_to_underscore() { | ||
135 | test_rename( | ||
136 | r#" | ||
137 | fn main() { | ||
138 | let i<|> = 1; | ||
139 | }"#, | ||
140 | "_", | ||
141 | r#" | ||
142 | fn main() { | ||
143 | let _ = 1; | ||
144 | }"#, | ||
145 | ); | ||
146 | } | ||
147 | |||
148 | #[test] | ||
149 | fn test_rename_to_raw_identifier() { | ||
150 | test_rename( | ||
151 | r#" | ||
152 | fn main() { | ||
153 | let i<|> = 1; | ||
154 | }"#, | ||
155 | "r#fn", | ||
156 | r#" | ||
157 | fn main() { | ||
158 | let r#fn = 1; | ||
159 | }"#, | ||
160 | ); | ||
161 | } | ||
162 | |||
163 | #[test] | ||
164 | fn test_rename_to_invalid_identifier() { | ||
165 | let (analysis, position) = single_file_with_position( | ||
166 | " | ||
167 | fn main() { | ||
168 | let i<|> = 1; | ||
169 | }", | ||
170 | ); | ||
171 | let new_name = "invalid!"; | ||
172 | let source_change = analysis.rename(position, new_name).unwrap(); | ||
173 | assert!(source_change.is_none()); | ||
174 | } | ||
175 | |||
176 | #[test] | ||
127 | fn test_rename_for_local() { | 177 | fn test_rename_for_local() { |
128 | test_rename( | 178 | test_rename( |
129 | r#" | 179 | r#" |
diff --git a/crates/ra_ide/src/references/search_scope.rs b/crates/ra_ide/src/references/search_scope.rs index f5c9589f4..241dd358f 100644 --- a/crates/ra_ide/src/references/search_scope.rs +++ b/crates/ra_ide/src/references/search_scope.rs | |||
@@ -5,7 +5,7 @@ | |||
5 | use std::mem; | 5 | use std::mem; |
6 | 6 | ||
7 | use hir::{DefWithBody, HasSource, ModuleSource}; | 7 | use hir::{DefWithBody, HasSource, ModuleSource}; |
8 | use ra_db::{FileId, SourceDatabase, SourceDatabaseExt}; | 8 | use ra_db::{FileId, SourceDatabaseExt}; |
9 | use ra_prof::profile; | 9 | use ra_prof::profile; |
10 | use ra_syntax::{AstNode, TextRange}; | 10 | use ra_syntax::{AstNode, TextRange}; |
11 | use rustc_hash::FxHashMap; | 11 | use rustc_hash::FxHashMap; |
@@ -120,15 +120,11 @@ impl NameDefinition { | |||
120 | } | 120 | } |
121 | if vis.as_str() == "pub" { | 121 | if vis.as_str() == "pub" { |
122 | let krate = self.container.krate(); | 122 | let krate = self.container.krate(); |
123 | let crate_graph = db.crate_graph(); | 123 | for rev_dep in krate.reverse_dependencies(db) { |
124 | for crate_id in crate_graph.iter() { | 124 | let root_file = rev_dep.root_file(db); |
125 | let mut crate_deps = crate_graph.dependencies(crate_id); | 125 | let source_root_id = db.file_source_root(root_file); |
126 | if crate_deps.any(|dep| dep.crate_id() == krate.crate_id()) { | 126 | let source_root = db.source_root(source_root_id); |
127 | let root_file = crate_graph.crate_root(crate_id); | 127 | res.extend(source_root.walk().map(|id| (id, None))); |
128 | let source_root_id = db.file_source_root(root_file); | ||
129 | let source_root = db.source_root(source_root_id); | ||
130 | res.extend(source_root.walk().map(|id| (id, None))); | ||
131 | } | ||
132 | } | 128 | } |
133 | return SearchScope::new(res); | 129 | return SearchScope::new(res); |
134 | } | 130 | } |