aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/references
diff options
context:
space:
mode:
authorSeivan Heidari <[email protected]>2019-12-23 14:35:31 +0000
committerSeivan Heidari <[email protected]>2019-12-23 14:35:31 +0000
commitb21d9337d9200e2cfdc90b386591c72c302dc03e (patch)
treef81f5c08f821115cee26fa4d3ceaae88c7807fd5 /crates/ra_ide/src/references
parent18a0937585b836ec5ed054b9ae48e0156ab6d9ef (diff)
parentce07a2daa9e53aa86a769f8641b14c2878444fbc (diff)
Merge branch 'master' into feature/themes
Diffstat (limited to 'crates/ra_ide/src/references')
-rw-r--r--crates/ra_ide/src/references/classify.rs29
-rw-r--r--crates/ra_ide/src/references/name_definition.rs6
-rw-r--r--crates/ra_ide/src/references/rename.rs54
-rw-r--r--crates/ra_ide/src/references/search_scope.rs16
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
3use hir::{FromSource, Module, ModuleSource, PathResolution, Source, SourceAnalyzer}; 3use hir::{FromSource, InFile, Module, ModuleSource, PathResolution, SourceAnalyzer};
4use ra_prof::profile; 4use ra_prof::profile;
5use ra_syntax::{ast, match_ast, AstNode}; 5use ra_syntax::{ast, match_ast, AstNode};
6use test_utils::tested_by; 6use test_utils::tested_by;
@@ -11,7 +11,7 @@ use super::{
11}; 11};
12use crate::db::RootDatabase; 12use crate::db::RootDatabase;
13 13
14pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Option<NameDefinition> { 14pub(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
118pub(crate) fn classify_name_ref( 127pub(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(&macro_call)) { 165 if let Some(macro_def) = analyzer.resolve_macro_call(db, name_ref.with_value(&macro_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
6use hir::{ 6use 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};
10use ra_syntax::{ast, ast::VisibilityOwner}; 10use 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
3use hir::ModuleSource; 3use hir::ModuleSource;
4use ra_db::{RelativePath, RelativePathBuf, SourceDatabase, SourceDatabaseExt}; 4use ra_db::{RelativePath, RelativePathBuf, SourceDatabase, SourceDatabaseExt};
5use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SyntaxNode}; 5use ra_syntax::{algo::find_node_at_offset, ast, tokenize, AstNode, SyntaxKind, SyntaxNode};
6use ra_text_edit::TextEdit; 6use ra_text_edit::TextEdit;
7 7
8use crate::{ 8use 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 @@
5use std::mem; 5use std::mem;
6 6
7use hir::{DefWithBody, HasSource, ModuleSource}; 7use hir::{DefWithBody, HasSource, ModuleSource};
8use ra_db::{FileId, SourceDatabase, SourceDatabaseExt}; 8use ra_db::{FileId, SourceDatabaseExt};
9use ra_prof::profile; 9use ra_prof::profile;
10use ra_syntax::{AstNode, TextRange}; 10use ra_syntax::{AstNode, TextRange};
11use rustc_hash::FxHashMap; 11use 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 }