diff options
Diffstat (limited to 'crates')
9 files changed, 195 insertions, 12 deletions
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index a6b9b41d0..6b253ac40 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use ra_db::FileId; | 1 | use ra_db::FileId; |
2 | use ra_syntax::ast; | 2 | use ra_syntax::{ast, SmolStr}; |
3 | use rustc_hash::FxHashMap; | 3 | use rustc_hash::FxHashMap; |
4 | use test_utils::tested_by; | 4 | use test_utils::tested_by; |
5 | 5 | ||
@@ -98,6 +98,7 @@ where | |||
98 | self.def_map.modules[module_id].definition = Some(file_id); | 98 | self.def_map.modules[module_id].definition = Some(file_id); |
99 | ModCollector { | 99 | ModCollector { |
100 | def_collector: &mut *self, | 100 | def_collector: &mut *self, |
101 | attr_path: None, | ||
101 | module_id, | 102 | module_id, |
102 | file_id: file_id.into(), | 103 | file_id: file_id.into(), |
103 | raw_items: &raw_items, | 104 | raw_items: &raw_items, |
@@ -474,6 +475,7 @@ where | |||
474 | ModCollector { | 475 | ModCollector { |
475 | def_collector: &mut *self, | 476 | def_collector: &mut *self, |
476 | file_id, | 477 | file_id, |
478 | attr_path: None, | ||
477 | module_id, | 479 | module_id, |
478 | raw_items: &raw_items, | 480 | raw_items: &raw_items, |
479 | parent_module: None, | 481 | parent_module: None, |
@@ -497,6 +499,7 @@ struct ModCollector<'a, D> { | |||
497 | def_collector: D, | 499 | def_collector: D, |
498 | module_id: CrateModuleId, | 500 | module_id: CrateModuleId, |
499 | file_id: HirFileId, | 501 | file_id: HirFileId, |
502 | attr_path: Option<&'a SmolStr>, | ||
500 | raw_items: &'a raw::RawItems, | 503 | raw_items: &'a raw::RawItems, |
501 | parent_module: Option<ParentModule<'a>>, | 504 | parent_module: Option<ParentModule<'a>>, |
502 | } | 505 | } |
@@ -551,6 +554,7 @@ where | |||
551 | ModCollector { | 554 | ModCollector { |
552 | def_collector: &mut *self.def_collector, | 555 | def_collector: &mut *self.def_collector, |
553 | module_id, | 556 | module_id, |
557 | attr_path: attr_path.as_ref(), | ||
554 | file_id: self.file_id, | 558 | file_id: self.file_id, |
555 | raw_items: self.raw_items, | 559 | raw_items: self.raw_items, |
556 | parent_module: Some(parent_module), | 560 | parent_module: Some(parent_module), |
@@ -567,6 +571,7 @@ where | |||
567 | match resolve_submodule( | 571 | match resolve_submodule( |
568 | self.def_collector.db, | 572 | self.def_collector.db, |
569 | self.file_id, | 573 | self.file_id, |
574 | self.attr_path, | ||
570 | name, | 575 | name, |
571 | is_root, | 576 | is_root, |
572 | attr_path.as_ref(), | 577 | attr_path.as_ref(), |
@@ -578,6 +583,7 @@ where | |||
578 | ModCollector { | 583 | ModCollector { |
579 | def_collector: &mut *self.def_collector, | 584 | def_collector: &mut *self.def_collector, |
580 | module_id, | 585 | module_id, |
586 | attr_path: attr_path.as_ref(), | ||
581 | file_id: file_id.into(), | 587 | file_id: file_id.into(), |
582 | raw_items: &raw_items, | 588 | raw_items: &raw_items, |
583 | parent_module: None, | 589 | parent_module: None, |
diff --git a/crates/ra_hir/src/nameres/mod_resolution.rs b/crates/ra_hir/src/nameres/mod_resolution.rs index a9e9eb9e6..3aa32bd66 100644 --- a/crates/ra_hir/src/nameres/mod_resolution.rs +++ b/crates/ra_hir/src/nameres/mod_resolution.rs | |||
@@ -23,6 +23,7 @@ impl<'a> ParentModule<'a> { | |||
23 | pub(super) fn resolve_submodule( | 23 | pub(super) fn resolve_submodule( |
24 | db: &impl DefDatabase, | 24 | db: &impl DefDatabase, |
25 | file_id: HirFileId, | 25 | file_id: HirFileId, |
26 | mod_attr_path: Option<&SmolStr>, | ||
26 | name: &Name, | 27 | name: &Name, |
27 | is_root: bool, | 28 | is_root: bool, |
28 | attr_path: Option<&SmolStr>, | 29 | attr_path: Option<&SmolStr>, |
@@ -80,7 +81,7 @@ pub(super) fn resolve_submodule( | |||
80 | ResolutionMode::OutOfLine(OutOfLineMode::WithAttributePath(path)) | 81 | ResolutionMode::OutOfLine(OutOfLineMode::WithAttributePath(path)) |
81 | } | 82 | } |
82 | (None, None) => { | 83 | (None, None) => { |
83 | let is_dir_owner = is_root || mod_name == "mod"; | 84 | let is_dir_owner = is_root || mod_name == "mod" || mod_attr_path.is_some(); |
84 | if is_dir_owner { | 85 | if is_dir_owner { |
85 | let file_mod = dir_path.join(format!("{}.rs", name)); | 86 | let file_mod = dir_path.join(format!("{}.rs", name)); |
86 | let dir_mod = dir_path.join(format!("{}/mod.rs", name)); | 87 | let dir_mod = dir_path.join(format!("{}/mod.rs", name)); |
diff --git a/crates/ra_hir/src/nameres/tests/mod_resolution.rs b/crates/ra_hir/src/nameres/tests/mod_resolution.rs index 4f8398460..e3e6f1e95 100644 --- a/crates/ra_hir/src/nameres/tests/mod_resolution.rs +++ b/crates/ra_hir/src/nameres/tests/mod_resolution.rs | |||
@@ -706,3 +706,34 @@ fn unresolved_module_diagnostics() { | |||
706 | "### | 706 | "### |
707 | ); | 707 | ); |
708 | } | 708 | } |
709 | |||
710 | #[test] | ||
711 | fn module_resolution_decl_inside_module_in_non_crate_root_2() { | ||
712 | let map = def_map_with_crate_graph( | ||
713 | r###" | ||
714 | //- /main.rs | ||
715 | #[path="module/m2.rs"] | ||
716 | mod module; | ||
717 | |||
718 | //- /module/m2.rs | ||
719 | pub mod submod; | ||
720 | |||
721 | //- /module/submod.rs | ||
722 | pub struct Baz; | ||
723 | "###, | ||
724 | crate_graph! { | ||
725 | "main": ("/main.rs", []), | ||
726 | }, | ||
727 | ); | ||
728 | |||
729 | assert_snapshot!(map, @r###" | ||
730 | ⋮crate | ||
731 | ⋮module: t | ||
732 | ⋮ | ||
733 | ⋮crate::module | ||
734 | ⋮submod: t | ||
735 | ⋮ | ||
736 | ⋮crate::module::submod | ||
737 | ⋮Baz: t v | ||
738 | "###); | ||
739 | } | ||
diff --git a/crates/ra_parser/src/grammar/items/use_item.rs b/crates/ra_parser/src/grammar/items/use_item.rs index 2af2ad315..63ac37e9e 100644 --- a/crates/ra_parser/src/grammar/items/use_item.rs +++ b/crates/ra_parser/src/grammar/items/use_item.rs | |||
@@ -3,7 +3,7 @@ use super::*; | |||
3 | pub(super) fn use_item(p: &mut Parser, m: Marker) { | 3 | pub(super) fn use_item(p: &mut Parser, m: Marker) { |
4 | assert!(p.at(T![use])); | 4 | assert!(p.at(T![use])); |
5 | p.bump(T![use]); | 5 | p.bump(T![use]); |
6 | use_tree(p); | 6 | use_tree(p, true); |
7 | p.expect(T![;]); | 7 | p.expect(T![;]); |
8 | m.complete(p, USE_ITEM); | 8 | m.complete(p, USE_ITEM); |
9 | } | 9 | } |
@@ -12,7 +12,7 @@ pub(super) fn use_item(p: &mut Parser, m: Marker) { | |||
12 | /// Note that this is called both by `use_item` and `use_tree_list`, | 12 | /// Note that this is called both by `use_item` and `use_tree_list`, |
13 | /// so handles both `some::path::{inner::path}` and `inner::path` in | 13 | /// so handles both `some::path::{inner::path}` and `inner::path` in |
14 | /// `use some::path::{inner::path};` | 14 | /// `use some::path::{inner::path};` |
15 | fn use_tree(p: &mut Parser) { | 15 | fn use_tree(p: &mut Parser, top_level: bool) { |
16 | let m = p.start(); | 16 | let m = p.start(); |
17 | match p.current() { | 17 | match p.current() { |
18 | // Finish the use_tree for cases of e.g. | 18 | // Finish the use_tree for cases of e.g. |
@@ -101,10 +101,14 @@ fn use_tree(p: &mut Parser) { | |||
101 | } | 101 | } |
102 | _ => { | 102 | _ => { |
103 | m.abandon(p); | 103 | m.abandon(p); |
104 | p.err_recover( | 104 | let msg = "expected one of `*`, `::`, `{`, `self`, `super` or an identifier"; |
105 | "expected one of `*`, `::`, `{`, `self`, `super` or an identifier", | 105 | if top_level { |
106 | ITEM_RECOVERY_SET, | 106 | p.err_recover(msg, ITEM_RECOVERY_SET); |
107 | ); | 107 | } else { |
108 | // if we are parsing a nested tree, we have to eat a token to | ||
109 | // main balanced `{}` | ||
110 | p.err_and_bump(msg); | ||
111 | } | ||
108 | return; | 112 | return; |
109 | } | 113 | } |
110 | } | 114 | } |
@@ -116,7 +120,7 @@ pub(crate) fn use_tree_list(p: &mut Parser) { | |||
116 | let m = p.start(); | 120 | let m = p.start(); |
117 | p.bump(T!['{']); | 121 | p.bump(T!['{']); |
118 | while !p.at(EOF) && !p.at(T!['}']) { | 122 | while !p.at(EOF) && !p.at(T!['}']) { |
119 | use_tree(p); | 123 | use_tree(p, false); |
120 | if !p.at(T!['}']) { | 124 | if !p.at(T!['}']) { |
121 | p.expect(T![,]); | 125 | p.expect(T![,]); |
122 | } | 126 | } |
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs index a4ffd6960..aa9a6d18e 100644 --- a/crates/ra_parser/src/grammar/patterns.rs +++ b/crates/ra_parser/src/grammar/patterns.rs | |||
@@ -167,7 +167,7 @@ fn record_field_pat_list(p: &mut Parser) { | |||
167 | // A trailing `..` is *not* treated as a DOT_DOT_PAT. | 167 | // A trailing `..` is *not* treated as a DOT_DOT_PAT. |
168 | T![.] if p.at(T![..]) => p.bump(T![..]), | 168 | T![.] if p.at(T![..]) => p.bump(T![..]), |
169 | 169 | ||
170 | IDENT if p.nth(1) == T![:] => record_field_pat(p), | 170 | IDENT | INT_NUMBER if p.nth(1) == T![:] => record_field_pat(p), |
171 | T!['{'] => error_block(p, "expected ident"), | 171 | T!['{'] => error_block(p, "expected ident"), |
172 | T![box] => { | 172 | T![box] => { |
173 | box_pat(p); | 173 | box_pat(p); |
@@ -184,12 +184,21 @@ fn record_field_pat_list(p: &mut Parser) { | |||
184 | m.complete(p, RECORD_FIELD_PAT_LIST); | 184 | m.complete(p, RECORD_FIELD_PAT_LIST); |
185 | } | 185 | } |
186 | 186 | ||
187 | // test record_field_pat | ||
188 | // fn foo() { | ||
189 | // let S { 0: 1 } = (); | ||
190 | // let S { x: 1 } = (); | ||
191 | // } | ||
187 | fn record_field_pat(p: &mut Parser) { | 192 | fn record_field_pat(p: &mut Parser) { |
188 | assert!(p.at(IDENT)); | 193 | assert!(p.at(IDENT) || p.at(INT_NUMBER)); |
189 | assert!(p.nth(1) == T![:]); | 194 | assert!(p.nth(1) == T![:]); |
190 | 195 | ||
191 | let m = p.start(); | 196 | let m = p.start(); |
192 | name(p); | 197 | |
198 | if !p.eat(INT_NUMBER) { | ||
199 | name(p) | ||
200 | } | ||
201 | |||
193 | p.bump_any(); | 202 | p.bump_any(); |
194 | pattern(p); | 203 | pattern(p); |
195 | m.complete(p, RECORD_FIELD_PAT); | 204 | m.complete(p, RECORD_FIELD_PAT); |
diff --git a/crates/ra_syntax/test_data/parser/err/0036_partial_use.rs b/crates/ra_syntax/test_data/parser/err/0036_partial_use.rs new file mode 100644 index 000000000..d521a5bb2 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/err/0036_partial_use.rs | |||
@@ -0,0 +1,2 @@ | |||
1 | use std::{error::Error; | ||
2 | use std::io; | ||
diff --git a/crates/ra_syntax/test_data/parser/err/0036_partial_use.txt b/crates/ra_syntax/test_data/parser/err/0036_partial_use.txt new file mode 100644 index 000000000..181f408c8 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/err/0036_partial_use.txt | |||
@@ -0,0 +1,51 @@ | |||
1 | SOURCE_FILE@[0; 37) | ||
2 | USE_ITEM@[0; 36) | ||
3 | USE_KW@[0; 3) "use" | ||
4 | WHITESPACE@[3; 4) " " | ||
5 | USE_TREE@[4; 36) | ||
6 | PATH@[4; 7) | ||
7 | PATH_SEGMENT@[4; 7) | ||
8 | NAME_REF@[4; 7) | ||
9 | IDENT@[4; 7) "std" | ||
10 | COLONCOLON@[7; 9) "::" | ||
11 | USE_TREE_LIST@[9; 36) | ||
12 | L_CURLY@[9; 10) "{" | ||
13 | USE_TREE@[10; 22) | ||
14 | PATH@[10; 22) | ||
15 | PATH@[10; 15) | ||
16 | PATH_SEGMENT@[10; 15) | ||
17 | NAME_REF@[10; 15) | ||
18 | IDENT@[10; 15) "error" | ||
19 | COLONCOLON@[15; 17) "::" | ||
20 | PATH_SEGMENT@[17; 22) | ||
21 | NAME_REF@[17; 22) | ||
22 | IDENT@[17; 22) "Error" | ||
23 | ERROR@[22; 23) | ||
24 | SEMI@[22; 23) ";" | ||
25 | WHITESPACE@[23; 24) "\n" | ||
26 | ERROR@[24; 27) | ||
27 | USE_KW@[24; 27) "use" | ||
28 | WHITESPACE@[27; 28) " " | ||
29 | USE_TREE@[28; 35) | ||
30 | PATH@[28; 35) | ||
31 | PATH@[28; 31) | ||
32 | PATH_SEGMENT@[28; 31) | ||
33 | NAME_REF@[28; 31) | ||
34 | IDENT@[28; 31) "std" | ||
35 | COLONCOLON@[31; 33) "::" | ||
36 | PATH_SEGMENT@[33; 35) | ||
37 | NAME_REF@[33; 35) | ||
38 | IDENT@[33; 35) "io" | ||
39 | ERROR@[35; 36) | ||
40 | SEMI@[35; 36) ";" | ||
41 | WHITESPACE@[36; 37) "\n" | ||
42 | error 22: expected COMMA | ||
43 | error 22: expected one of `*`, `::`, `{`, `self`, `super` or an identifier | ||
44 | error 23: expected COMMA | ||
45 | error 24: expected one of `*`, `::`, `{`, `self`, `super` or an identifier | ||
46 | error 27: expected COMMA | ||
47 | error 35: expected COMMA | ||
48 | error 35: expected one of `*`, `::`, `{`, `self`, `super` or an identifier | ||
49 | error 36: expected COMMA | ||
50 | error 36: expected R_CURLY | ||
51 | error 36: expected SEMI | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0145_record_field_pat.rs b/crates/ra_syntax/test_data/parser/inline/ok/0145_record_field_pat.rs new file mode 100644 index 000000000..26b1d5f89 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0145_record_field_pat.rs | |||
@@ -0,0 +1,4 @@ | |||
1 | fn foo() { | ||
2 | let S { 0: 1 } = (); | ||
3 | let S { x: 1 } = (); | ||
4 | } | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0145_record_field_pat.txt b/crates/ra_syntax/test_data/parser/inline/ok/0145_record_field_pat.txt new file mode 100644 index 000000000..06fbdfabf --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0145_record_field_pat.txt | |||
@@ -0,0 +1,75 @@ | |||
1 | SOURCE_FILE@[0; 63) | ||
2 | FN_DEF@[0; 62) | ||
3 | FN_KW@[0; 2) "fn" | ||
4 | WHITESPACE@[2; 3) " " | ||
5 | NAME@[3; 6) | ||
6 | IDENT@[3; 6) "foo" | ||
7 | PARAM_LIST@[6; 8) | ||
8 | L_PAREN@[6; 7) "(" | ||
9 | R_PAREN@[7; 8) ")" | ||
10 | WHITESPACE@[8; 9) " " | ||
11 | BLOCK_EXPR@[9; 62) | ||
12 | BLOCK@[9; 62) | ||
13 | L_CURLY@[9; 10) "{" | ||
14 | WHITESPACE@[10; 15) "\n " | ||
15 | LET_STMT@[15; 35) | ||
16 | LET_KW@[15; 18) "let" | ||
17 | WHITESPACE@[18; 19) " " | ||
18 | RECORD_PAT@[19; 29) | ||
19 | PATH@[19; 20) | ||
20 | PATH_SEGMENT@[19; 20) | ||
21 | NAME_REF@[19; 20) | ||
22 | IDENT@[19; 20) "S" | ||
23 | WHITESPACE@[20; 21) " " | ||
24 | RECORD_FIELD_PAT_LIST@[21; 29) | ||
25 | L_CURLY@[21; 22) "{" | ||
26 | WHITESPACE@[22; 23) " " | ||
27 | RECORD_FIELD_PAT@[23; 27) | ||
28 | INT_NUMBER@[23; 24) "0" | ||
29 | COLON@[24; 25) ":" | ||
30 | WHITESPACE@[25; 26) " " | ||
31 | LITERAL_PAT@[26; 27) | ||
32 | LITERAL@[26; 27) | ||
33 | INT_NUMBER@[26; 27) "1" | ||
34 | WHITESPACE@[27; 28) " " | ||
35 | R_CURLY@[28; 29) "}" | ||
36 | WHITESPACE@[29; 30) " " | ||
37 | EQ@[30; 31) "=" | ||
38 | WHITESPACE@[31; 32) " " | ||
39 | TUPLE_EXPR@[32; 34) | ||
40 | L_PAREN@[32; 33) "(" | ||
41 | R_PAREN@[33; 34) ")" | ||
42 | SEMI@[34; 35) ";" | ||
43 | WHITESPACE@[35; 40) "\n " | ||
44 | LET_STMT@[40; 60) | ||
45 | LET_KW@[40; 43) "let" | ||
46 | WHITESPACE@[43; 44) " " | ||
47 | RECORD_PAT@[44; 54) | ||
48 | PATH@[44; 45) | ||
49 | PATH_SEGMENT@[44; 45) | ||
50 | NAME_REF@[44; 45) | ||
51 | IDENT@[44; 45) "S" | ||
52 | WHITESPACE@[45; 46) " " | ||
53 | RECORD_FIELD_PAT_LIST@[46; 54) | ||
54 | L_CURLY@[46; 47) "{" | ||
55 | WHITESPACE@[47; 48) " " | ||
56 | RECORD_FIELD_PAT@[48; 52) | ||
57 | NAME@[48; 49) | ||
58 | IDENT@[48; 49) "x" | ||
59 | COLON@[49; 50) ":" | ||
60 | WHITESPACE@[50; 51) " " | ||
61 | LITERAL_PAT@[51; 52) | ||
62 | LITERAL@[51; 52) | ||
63 | INT_NUMBER@[51; 52) "1" | ||
64 | WHITESPACE@[52; 53) " " | ||
65 | R_CURLY@[53; 54) "}" | ||
66 | WHITESPACE@[54; 55) " " | ||
67 | EQ@[55; 56) "=" | ||
68 | WHITESPACE@[56; 57) " " | ||
69 | TUPLE_EXPR@[57; 59) | ||
70 | L_PAREN@[57; 58) "(" | ||
71 | R_PAREN@[58; 59) ")" | ||
72 | SEMI@[59; 60) ";" | ||
73 | WHITESPACE@[60; 61) "\n" | ||
74 | R_CURLY@[61; 62) "}" | ||
75 | WHITESPACE@[62; 63) "\n" | ||