diff options
-rw-r--r-- | crates/ra_db/src/input.rs | 82 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model_impl/function/scope.rs | 31 | ||||
-rw-r--r-- | crates/ra_hir/src/expr.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests.rs | 12 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/server_world.rs | 25 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast.rs | 6 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/generated.rs | 6 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar.ron | 2 |
8 files changed, 124 insertions, 52 deletions
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs index 023183e29..2b761ea0c 100644 --- a/crates/ra_db/src/input.rs +++ b/crates/ra_db/src/input.rs | |||
@@ -53,6 +53,9 @@ pub struct CrateGraph { | |||
53 | arena: FxHashMap<CrateId, CrateData>, | 53 | arena: FxHashMap<CrateId, CrateData>, |
54 | } | 54 | } |
55 | 55 | ||
56 | #[derive(Debug)] | ||
57 | pub struct CyclicDependencies; | ||
58 | |||
56 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | 59 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
57 | pub struct CrateId(pub u32); | 60 | pub struct CrateId(pub u32); |
58 | 61 | ||
@@ -94,12 +97,16 @@ impl CrateGraph { | |||
94 | assert!(prev.is_none()); | 97 | assert!(prev.is_none()); |
95 | crate_id | 98 | crate_id |
96 | } | 99 | } |
97 | pub fn add_dep(&mut self, from: CrateId, name: SmolStr, to: CrateId) { | 100 | pub fn add_dep( |
98 | let mut visited = FxHashSet::default(); | 101 | &mut self, |
99 | if self.dfs_find(from, to, &mut visited) { | 102 | from: CrateId, |
100 | panic!("Cycle dependencies found.") | 103 | name: SmolStr, |
104 | to: CrateId, | ||
105 | ) -> Result<(), CyclicDependencies> { | ||
106 | if self.dfs_find(from, to, &mut FxHashSet::default()) { | ||
107 | return Err(CyclicDependencies); | ||
101 | } | 108 | } |
102 | self.arena.get_mut(&from).unwrap().add_dep(name, to) | 109 | Ok(self.arena.get_mut(&from).unwrap().add_dep(name, to)) |
103 | } | 110 | } |
104 | pub fn is_empty(&self) -> bool { | 111 | pub fn is_empty(&self) -> bool { |
105 | self.arena.is_empty() | 112 | self.arena.is_empty() |
@@ -139,35 +146,6 @@ impl CrateGraph { | |||
139 | } | 146 | } |
140 | } | 147 | } |
141 | 148 | ||
142 | #[cfg(test)] | ||
143 | mod tests { | ||
144 | use super::{CrateGraph, FxHashMap, FileId, SmolStr}; | ||
145 | |||
146 | #[test] | ||
147 | #[should_panic] | ||
148 | fn it_should_painc_because_of_cycle_dependencies() { | ||
149 | let mut graph = CrateGraph::default(); | ||
150 | let crate1 = graph.add_crate_root(FileId(1u32)); | ||
151 | let crate2 = graph.add_crate_root(FileId(2u32)); | ||
152 | let crate3 = graph.add_crate_root(FileId(3u32)); | ||
153 | graph.add_dep(crate1, SmolStr::new("crate2"), crate2); | ||
154 | graph.add_dep(crate2, SmolStr::new("crate3"), crate3); | ||
155 | graph.add_dep(crate3, SmolStr::new("crate1"), crate1); | ||
156 | } | ||
157 | |||
158 | #[test] | ||
159 | fn it_works() { | ||
160 | let mut graph = CrateGraph { | ||
161 | arena: FxHashMap::default(), | ||
162 | }; | ||
163 | let crate1 = graph.add_crate_root(FileId(1u32)); | ||
164 | let crate2 = graph.add_crate_root(FileId(2u32)); | ||
165 | let crate3 = graph.add_crate_root(FileId(3u32)); | ||
166 | graph.add_dep(crate1, SmolStr::new("crate2"), crate2); | ||
167 | graph.add_dep(crate2, SmolStr::new("crate3"), crate3); | ||
168 | } | ||
169 | } | ||
170 | |||
171 | salsa::query_group! { | 149 | salsa::query_group! { |
172 | pub trait FilesDatabase: salsa::Database { | 150 | pub trait FilesDatabase: salsa::Database { |
173 | /// Text of the file. | 151 | /// Text of the file. |
@@ -209,3 +187,39 @@ salsa::query_group! { | |||
209 | } | 187 | } |
210 | } | 188 | } |
211 | } | 189 | } |
190 | |||
191 | #[cfg(test)] | ||
192 | mod tests { | ||
193 | use super::{CrateGraph, FileId, SmolStr}; | ||
194 | |||
195 | #[test] | ||
196 | fn it_should_painc_because_of_cycle_dependencies() { | ||
197 | let mut graph = CrateGraph::default(); | ||
198 | let crate1 = graph.add_crate_root(FileId(1u32)); | ||
199 | let crate2 = graph.add_crate_root(FileId(2u32)); | ||
200 | let crate3 = graph.add_crate_root(FileId(3u32)); | ||
201 | assert!(graph | ||
202 | .add_dep(crate1, SmolStr::new("crate2"), crate2) | ||
203 | .is_ok()); | ||
204 | assert!(graph | ||
205 | .add_dep(crate2, SmolStr::new("crate3"), crate3) | ||
206 | .is_ok()); | ||
207 | assert!(graph | ||
208 | .add_dep(crate3, SmolStr::new("crate1"), crate1) | ||
209 | .is_err()); | ||
210 | } | ||
211 | |||
212 | #[test] | ||
213 | fn it_works() { | ||
214 | let mut graph = CrateGraph::default(); | ||
215 | let crate1 = graph.add_crate_root(FileId(1u32)); | ||
216 | let crate2 = graph.add_crate_root(FileId(2u32)); | ||
217 | let crate3 = graph.add_crate_root(FileId(3u32)); | ||
218 | assert!(graph | ||
219 | .add_dep(crate1, SmolStr::new("crate2"), crate2) | ||
220 | .is_ok()); | ||
221 | assert!(graph | ||
222 | .add_dep(crate2, SmolStr::new("crate3"), crate3) | ||
223 | .is_ok()); | ||
224 | } | ||
225 | } | ||
diff --git a/crates/ra_hir/src/code_model_impl/function/scope.rs b/crates/ra_hir/src/code_model_impl/function/scope.rs index 7d938c0dd..afca1e9f8 100644 --- a/crates/ra_hir/src/code_model_impl/function/scope.rs +++ b/crates/ra_hir/src/code_model_impl/function/scope.rs | |||
@@ -422,6 +422,9 @@ mod tests { | |||
422 | fn do_check_local_name(code: &str, expected_offset: u32) { | 422 | fn do_check_local_name(code: &str, expected_offset: u32) { |
423 | let (off, code) = extract_offset(code); | 423 | let (off, code) = extract_offset(code); |
424 | let file = SourceFile::parse(&code); | 424 | let file = SourceFile::parse(&code); |
425 | let expected_name = find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into()) | ||
426 | .expect("failed to find a name at the target offset"); | ||
427 | |||
425 | let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); | 428 | let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); |
426 | let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); | 429 | let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); |
427 | 430 | ||
@@ -431,11 +434,8 @@ mod tests { | |||
431 | scopes: Arc::new(scopes), | 434 | scopes: Arc::new(scopes), |
432 | syntax_mapping: Arc::new(body_hir), | 435 | syntax_mapping: Arc::new(body_hir), |
433 | }; | 436 | }; |
434 | |||
435 | let local_name_entry = scopes.resolve_local_name(name_ref).unwrap(); | 437 | let local_name_entry = scopes.resolve_local_name(name_ref).unwrap(); |
436 | let local_name = local_name_entry.ptr(); | 438 | let local_name = local_name_entry.ptr(); |
437 | let expected_name = | ||
438 | find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into()).unwrap(); | ||
439 | assert_eq!(local_name.range(), expected_name.syntax().range()); | 439 | assert_eq!(local_name.range(), expected_name.syntax().range()); |
440 | } | 440 | } |
441 | 441 | ||
@@ -470,11 +470,26 @@ mod tests { | |||
470 | fn test_resolve_local_name_shadow() { | 470 | fn test_resolve_local_name_shadow() { |
471 | do_check_local_name( | 471 | do_check_local_name( |
472 | r" | 472 | r" |
473 | fn foo(x: String) { | 473 | fn foo(x: String) { |
474 | let x : &str = &x; | 474 | let x : &str = &x; |
475 | x<|> | 475 | x<|> |
476 | }", | 476 | } |
477 | 46, | 477 | ", |
478 | 53, | ||
479 | ); | ||
480 | } | ||
481 | |||
482 | #[test] | ||
483 | fn ref_patterns_contribute_bindings() { | ||
484 | do_check_local_name( | ||
485 | r" | ||
486 | fn foo() { | ||
487 | if let Some(&from) = bar() { | ||
488 | from<|>; | ||
489 | } | ||
490 | } | ||
491 | ", | ||
492 | 53, | ||
478 | ); | 493 | ); |
479 | } | 494 | } |
480 | } | 495 | } |
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 67e123e4d..593fe1598 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -315,15 +315,20 @@ pub enum Pat { | |||
315 | path: Option<Path>, | 315 | path: Option<Path>, |
316 | args: Vec<PatId>, | 316 | args: Vec<PatId>, |
317 | }, | 317 | }, |
318 | Ref { | ||
319 | pat: PatId, | ||
320 | mutability: Mutability, | ||
321 | }, | ||
318 | } | 322 | } |
319 | 323 | ||
320 | impl Pat { | 324 | impl Pat { |
321 | pub fn walk_child_pats(&self, f: impl FnMut(PatId)) { | 325 | pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) { |
322 | match self { | 326 | match self { |
323 | Pat::Missing | Pat::Bind { .. } => {} | 327 | Pat::Missing | Pat::Bind { .. } => {} |
324 | Pat::TupleStruct { args, .. } => { | 328 | Pat::TupleStruct { args, .. } => { |
325 | args.iter().map(|pat| *pat).for_each(f); | 329 | args.iter().map(|pat| *pat).for_each(f); |
326 | } | 330 | } |
331 | Pat::Ref { pat, .. } => f(*pat), | ||
327 | } | 332 | } |
328 | } | 333 | } |
329 | } | 334 | } |
@@ -684,6 +689,11 @@ impl ExprCollector { | |||
684 | let args = p.args().map(|p| self.collect_pat(p)).collect(); | 689 | let args = p.args().map(|p| self.collect_pat(p)).collect(); |
685 | self.alloc_pat(Pat::TupleStruct { path, args }, syntax_ptr) | 690 | self.alloc_pat(Pat::TupleStruct { path, args }, syntax_ptr) |
686 | } | 691 | } |
692 | ast::PatKind::RefPat(p) => { | ||
693 | let pat = self.collect_pat_opt(p.pat()); | ||
694 | let mutability = Mutability::from_mutable(p.is_mut()); | ||
695 | self.alloc_pat(Pat::Ref { pat, mutability }, syntax_ptr) | ||
696 | } | ||
687 | _ => { | 697 | _ => { |
688 | // TODO | 698 | // TODO |
689 | self.alloc_pat(Pat::Missing, syntax_ptr) | 699 | self.alloc_pat(Pat::Missing, syntax_ptr) |
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index ba9fcb3d1..647fd92aa 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs | |||
@@ -235,7 +235,9 @@ fn item_map_across_crates() { | |||
235 | let mut crate_graph = CrateGraph::default(); | 235 | let mut crate_graph = CrateGraph::default(); |
236 | let main_crate = crate_graph.add_crate_root(main_id); | 236 | let main_crate = crate_graph.add_crate_root(main_id); |
237 | let lib_crate = crate_graph.add_crate_root(lib_id); | 237 | let lib_crate = crate_graph.add_crate_root(lib_id); |
238 | crate_graph.add_dep(main_crate, "test_crate".into(), lib_crate); | 238 | crate_graph |
239 | .add_dep(main_crate, "test_crate".into(), lib_crate) | ||
240 | .unwrap(); | ||
239 | 241 | ||
240 | db.set_crate_graph(crate_graph); | 242 | db.set_crate_graph(crate_graph); |
241 | 243 | ||
@@ -288,7 +290,9 @@ fn import_across_source_roots() { | |||
288 | let mut crate_graph = CrateGraph::default(); | 290 | let mut crate_graph = CrateGraph::default(); |
289 | let main_crate = crate_graph.add_crate_root(main_id); | 291 | let main_crate = crate_graph.add_crate_root(main_id); |
290 | let lib_crate = crate_graph.add_crate_root(lib_id); | 292 | let lib_crate = crate_graph.add_crate_root(lib_id); |
291 | crate_graph.add_dep(main_crate, "test_crate".into(), lib_crate); | 293 | crate_graph |
294 | .add_dep(main_crate, "test_crate".into(), lib_crate) | ||
295 | .unwrap(); | ||
292 | 296 | ||
293 | db.set_crate_graph(crate_graph); | 297 | db.set_crate_graph(crate_graph); |
294 | 298 | ||
@@ -330,7 +334,9 @@ fn reexport_across_crates() { | |||
330 | let mut crate_graph = CrateGraph::default(); | 334 | let mut crate_graph = CrateGraph::default(); |
331 | let main_crate = crate_graph.add_crate_root(main_id); | 335 | let main_crate = crate_graph.add_crate_root(main_id); |
332 | let lib_crate = crate_graph.add_crate_root(lib_id); | 336 | let lib_crate = crate_graph.add_crate_root(lib_id); |
333 | crate_graph.add_dep(main_crate, "test_crate".into(), lib_crate); | 337 | crate_graph |
338 | .add_dep(main_crate, "test_crate".into(), lib_crate) | ||
339 | .unwrap(); | ||
334 | 340 | ||
335 | db.set_crate_graph(crate_graph); | 341 | db.set_crate_graph(crate_graph); |
336 | 342 | ||
diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs index 4f3c231d3..d5dbf999f 100644 --- a/crates/ra_lsp_server/src/server_world.rs +++ b/crates/ra_lsp_server/src/server_world.rs | |||
@@ -73,7 +73,9 @@ impl ServerWorldState { | |||
73 | if let (Some(&from), Some(&to)) = | 73 | if let (Some(&from), Some(&to)) = |
74 | (sysroot_crates.get(&from), sysroot_crates.get(&to)) | 74 | (sysroot_crates.get(&from), sysroot_crates.get(&to)) |
75 | { | 75 | { |
76 | crate_graph.add_dep(from, name.clone(), to); | 76 | if let Err(_) = crate_graph.add_dep(from, name.clone(), to) { |
77 | log::error!("cyclic dependency between sysroot crates") | ||
78 | } | ||
77 | } | 79 | } |
78 | } | 80 | } |
79 | } | 81 | } |
@@ -108,11 +110,20 @@ impl ServerWorldState { | |||
108 | for &from in pkg_crates.get(&pkg).into_iter().flatten() { | 110 | for &from in pkg_crates.get(&pkg).into_iter().flatten() { |
109 | if let Some(to) = lib_tgt { | 111 | if let Some(to) = lib_tgt { |
110 | if to != from { | 112 | if to != from { |
111 | crate_graph.add_dep(from, pkg.name(&ws.cargo).into(), to); | 113 | if let Err(_) = |
114 | crate_graph.add_dep(from, pkg.name(&ws.cargo).into(), to) | ||
115 | { | ||
116 | log::error!( | ||
117 | "cyclic dependency between targets of {}", | ||
118 | pkg.name(&ws.cargo) | ||
119 | ) | ||
120 | } | ||
112 | } | 121 | } |
113 | } | 122 | } |
114 | if let Some(std) = libstd { | 123 | if let Some(std) = libstd { |
115 | crate_graph.add_dep(from, "std".into(), std); | 124 | if let Err(_) = crate_graph.add_dep(from, "std".into(), std) { |
125 | log::error!("cyclic dependency on std for {}", pkg.name(&ws.cargo)) | ||
126 | } | ||
116 | } | 127 | } |
117 | } | 128 | } |
118 | } | 129 | } |
@@ -123,7 +134,13 @@ impl ServerWorldState { | |||
123 | for dep in pkg.dependencies(&ws.cargo) { | 134 | for dep in pkg.dependencies(&ws.cargo) { |
124 | if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { | 135 | if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { |
125 | for &from in pkg_crates.get(&pkg).into_iter().flatten() { | 136 | for &from in pkg_crates.get(&pkg).into_iter().flatten() { |
126 | crate_graph.add_dep(from, dep.name.clone(), to); | 137 | if let Err(_) = crate_graph.add_dep(from, dep.name.clone(), to) { |
138 | log::error!( | ||
139 | "cyclic dependency {} -> {}", | ||
140 | pkg.name(&ws.cargo), | ||
141 | dep.pkg.name(&ws.cargo) | ||
142 | ) | ||
143 | } | ||
127 | } | 144 | } |
128 | } | 145 | } |
129 | } | 146 | } |
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 123a7a6b9..8bf439b60 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs | |||
@@ -348,6 +348,12 @@ impl UseTreeList { | |||
348 | } | 348 | } |
349 | } | 349 | } |
350 | 350 | ||
351 | impl RefPat { | ||
352 | pub fn is_mut(&self) -> bool { | ||
353 | self.syntax().children().any(|n| n.kind() == MUT_KW) | ||
354 | } | ||
355 | } | ||
356 | |||
351 | fn child_opt<P: AstNode, C: AstNode>(parent: &P) -> Option<&C> { | 357 | fn child_opt<P: AstNode, C: AstNode>(parent: &P) -> Option<&C> { |
352 | children(parent).next() | 358 | children(parent).next() |
353 | } | 359 | } |
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 1f6055115..f745cb1cb 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs | |||
@@ -2456,7 +2456,11 @@ impl AstNode for RefPat { | |||
2456 | } | 2456 | } |
2457 | 2457 | ||
2458 | 2458 | ||
2459 | impl RefPat {} | 2459 | impl RefPat { |
2460 | pub fn pat(&self) -> Option<&Pat> { | ||
2461 | super::child_opt(self) | ||
2462 | } | ||
2463 | } | ||
2460 | 2464 | ||
2461 | // ReferenceType | 2465 | // ReferenceType |
2462 | #[derive(Debug, PartialEq, Eq, Hash)] | 2466 | #[derive(Debug, PartialEq, Eq, Hash)] |
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index bddd96a5c..bac62fa04 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron | |||
@@ -462,7 +462,7 @@ Grammar( | |||
462 | ], | 462 | ], |
463 | ), | 463 | ), |
464 | 464 | ||
465 | "RefPat": (), | 465 | "RefPat": ( options: [ "Pat" ]), |
466 | "BindPat": ( traits: ["NameOwner"] ), | 466 | "BindPat": ( traits: ["NameOwner"] ), |
467 | "PlaceholderPat": (), | 467 | "PlaceholderPat": (), |
468 | "PathPat": (), | 468 | "PathPat": (), |