diff options
-rw-r--r-- | crates/ra_assists/src/handlers/change_visibility.rs | 13 | ||||
-rw-r--r-- | crates/ra_ide/src/hover.rs | 98 | ||||
-rw-r--r-- | crates/ra_ide/src/lib.rs | 5 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/expressions.rs | 3 | ||||
-rw-r--r-- | crates/ra_syntax/test_data/parser/inline/ok/0130_let_stmt.rs | 1 | ||||
-rw-r--r-- | crates/ra_syntax/test_data/parser/inline/ok/0130_let_stmt.txt | 41 |
6 files changed, 70 insertions, 91 deletions
diff --git a/crates/ra_assists/src/handlers/change_visibility.rs b/crates/ra_assists/src/handlers/change_visibility.rs index f325b6f92..54e0a6c84 100644 --- a/crates/ra_assists/src/handlers/change_visibility.rs +++ b/crates/ra_assists/src/handlers/change_visibility.rs | |||
@@ -2,8 +2,8 @@ use ra_syntax::{ | |||
2 | ast::{self, NameOwner, VisibilityOwner}, | 2 | ast::{self, NameOwner, VisibilityOwner}, |
3 | AstNode, | 3 | AstNode, |
4 | SyntaxKind::{ | 4 | SyntaxKind::{ |
5 | ATTR, COMMENT, ENUM_DEF, FN_DEF, IDENT, MODULE, STRUCT_DEF, TRAIT_DEF, VISIBILITY, | 5 | ATTR, COMMENT, CONST_DEF, ENUM_DEF, FN_DEF, IDENT, MODULE, STRUCT_DEF, TRAIT_DEF, |
6 | WHITESPACE, | 6 | VISIBILITY, WHITESPACE, |
7 | }, | 7 | }, |
8 | SyntaxNode, TextUnit, T, | 8 | SyntaxNode, TextUnit, T, |
9 | }; | 9 | }; |
@@ -30,13 +30,13 @@ pub(crate) fn change_visibility(ctx: AssistCtx) -> Option<Assist> { | |||
30 | 30 | ||
31 | fn add_vis(ctx: AssistCtx) -> Option<Assist> { | 31 | fn add_vis(ctx: AssistCtx) -> Option<Assist> { |
32 | let item_keyword = ctx.token_at_offset().find(|leaf| match leaf.kind() { | 32 | let item_keyword = ctx.token_at_offset().find(|leaf| match leaf.kind() { |
33 | T![fn] | T![mod] | T![struct] | T![enum] | T![trait] => true, | 33 | T![const] | T![fn] | T![mod] | T![struct] | T![enum] | T![trait] => true, |
34 | _ => false, | 34 | _ => false, |
35 | }); | 35 | }); |
36 | 36 | ||
37 | let (offset, target) = if let Some(keyword) = item_keyword { | 37 | let (offset, target) = if let Some(keyword) = item_keyword { |
38 | let parent = keyword.parent(); | 38 | let parent = keyword.parent(); |
39 | let def_kws = vec![FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF]; | 39 | let def_kws = vec![CONST_DEF, FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF]; |
40 | // Parent is not a definition, can't add visibility | 40 | // Parent is not a definition, can't add visibility |
41 | if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) { | 41 | if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) { |
42 | return None; | 42 | return None; |
@@ -136,6 +136,11 @@ mod tests { | |||
136 | } | 136 | } |
137 | 137 | ||
138 | #[test] | 138 | #[test] |
139 | fn change_visibility_const() { | ||
140 | check_assist(change_visibility, "<|>const FOO = 3u8;", "<|>pub(crate) const FOO = 3u8;"); | ||
141 | } | ||
142 | |||
143 | #[test] | ||
139 | fn change_visibility_handles_comment_attrs() { | 144 | fn change_visibility_handles_comment_attrs() { |
140 | check_assist( | 145 | check_assist( |
141 | change_visibility, | 146 | change_visibility, |
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index dfa0f1d97..7ba4bfcac 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs | |||
@@ -6,7 +6,6 @@ use ra_ide_db::{ | |||
6 | RootDatabase, | 6 | RootDatabase, |
7 | }; | 7 | }; |
8 | use ra_syntax::{ | 8 | use ra_syntax::{ |
9 | algo::find_covering_element, | ||
10 | ast::{self, DocCommentsOwner}, | 9 | ast::{self, DocCommentsOwner}, |
11 | match_ast, AstNode, | 10 | match_ast, AstNode, |
12 | SyntaxKind::*, | 11 | SyntaxKind::*, |
@@ -16,7 +15,7 @@ use ra_syntax::{ | |||
16 | use crate::{ | 15 | use crate::{ |
17 | display::{macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel}, | 16 | display::{macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel}, |
18 | references::classify_name_ref, | 17 | references::classify_name_ref, |
19 | FilePosition, FileRange, RangeInfo, | 18 | FilePosition, RangeInfo, |
20 | }; | 19 | }; |
21 | 20 | ||
22 | /// Contains the results when hovering over an item | 21 | /// Contains the results when hovering over an item |
@@ -174,23 +173,25 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn | |||
174 | .ancestors() | 173 | .ancestors() |
175 | .find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some())?; | 174 | .find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some())?; |
176 | 175 | ||
177 | // if this node is a MACRO_CALL, it means that `descend_into_macros` is failed to resolve. | 176 | let ty = match_ast! { |
178 | // (e.g expanding a builtin macro). So we give up here. | 177 | match node { |
179 | if node.kind() == MACRO_CALL { | 178 | ast::MacroCall(_it) => { |
180 | return None; | 179 | // If this node is a MACRO_CALL, it means that `descend_into_macros` failed to resolve. |
181 | } | 180 | // (e.g expanding a builtin macro). So we give up here. |
182 | 181 | return None; | |
183 | // FIXME: Currently `hover::typeof` do not work inside | 182 | }, |
184 | // macro expansion such that if the hover range is pointing to | 183 | ast::Expr(it) => { |
185 | // a string literal, the following type_of will return None. | 184 | sema.type_of_expr(&it) |
186 | // See also `test_hover_through_literal_string_in_macro` | 185 | }, |
187 | let frange = sema.original_range(&node); | 186 | ast::Pat(it) => { |
188 | res.extend(type_of(db, frange).map(rust_code_markup)); | 187 | sema.type_of_pat(&it) |
189 | if res.is_empty() { | 188 | }, |
190 | return None; | 189 | _ => None, |
191 | } | 190 | } |
192 | let range = node.text_range(); | 191 | }?; |
193 | 192 | ||
193 | res.extend(Some(rust_code_markup(ty.display_truncated(db, None).to_string()))); | ||
194 | let range = sema.original_range(&node).range; | ||
194 | Some(RangeInfo::new(range, res)) | 195 | Some(RangeInfo::new(range, res)) |
195 | } | 196 | } |
196 | 197 | ||
@@ -206,33 +207,12 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { | |||
206 | } | 207 | } |
207 | } | 208 | } |
208 | 209 | ||
209 | pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option<String> { | ||
210 | let sema = Semantics::new(db); | ||
211 | let source_file = sema.parse(frange.file_id); | ||
212 | let leaf_node = find_covering_element(source_file.syntax(), frange.range); | ||
213 | // if we picked identifier, expand to pattern/expression | ||
214 | let node = leaf_node | ||
215 | .ancestors() | ||
216 | .take_while(|it| it.text_range() == leaf_node.text_range()) | ||
217 | .find(|it| ast::Expr::cast(it.clone()).is_some() || ast::Pat::cast(it.clone()).is_some())?; | ||
218 | let ty = if let Some(ty) = ast::Expr::cast(node.clone()).and_then(|e| sema.type_of_expr(&e)) { | ||
219 | ty | ||
220 | } else if let Some(ty) = ast::Pat::cast(node).and_then(|p| sema.type_of_pat(&p)) { | ||
221 | ty | ||
222 | } else { | ||
223 | return None; | ||
224 | }; | ||
225 | Some(ty.display_truncated(db, None).to_string()) | ||
226 | } | ||
227 | |||
228 | #[cfg(test)] | 210 | #[cfg(test)] |
229 | mod tests { | 211 | mod tests { |
230 | use ra_db::FileLoader; | 212 | use ra_db::FileLoader; |
231 | use ra_syntax::TextRange; | 213 | use ra_syntax::TextRange; |
232 | 214 | ||
233 | use crate::mock_analysis::{ | 215 | use crate::mock_analysis::{analysis_and_position, single_file_with_position}; |
234 | analysis_and_position, single_file_with_position, single_file_with_range, | ||
235 | }; | ||
236 | 216 | ||
237 | fn trim_markup(s: &str) -> &str { | 217 | fn trim_markup(s: &str) -> &str { |
238 | s.trim_start_matches("```rust\n").trim_end_matches("\n```") | 218 | s.trim_start_matches("```rust\n").trim_end_matches("\n```") |
@@ -525,37 +505,6 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
525 | } | 505 | } |
526 | 506 | ||
527 | #[test] | 507 | #[test] |
528 | fn test_type_of_for_function() { | ||
529 | let (analysis, range) = single_file_with_range( | ||
530 | " | ||
531 | pub fn foo() -> u32 { 1 }; | ||
532 | |||
533 | fn main() { | ||
534 | let foo_test = <|>foo()<|>; | ||
535 | } | ||
536 | ", | ||
537 | ); | ||
538 | |||
539 | let type_name = analysis.type_of(range).unwrap().unwrap(); | ||
540 | assert_eq!("u32", &type_name); | ||
541 | } | ||
542 | |||
543 | #[test] | ||
544 | fn test_type_of_for_expr() { | ||
545 | let (analysis, range) = single_file_with_range( | ||
546 | " | ||
547 | fn main() { | ||
548 | let foo: usize = 1; | ||
549 | let bar = <|>1 + foo<|>; | ||
550 | } | ||
551 | ", | ||
552 | ); | ||
553 | |||
554 | let type_name = analysis.type_of(range).unwrap().unwrap(); | ||
555 | assert_eq!("usize", &type_name); | ||
556 | } | ||
557 | |||
558 | #[test] | ||
559 | fn test_hover_infer_associated_method_result() { | 508 | fn test_hover_infer_associated_method_result() { |
560 | let (analysis, position) = single_file_with_position( | 509 | let (analysis, position) = single_file_with_position( |
561 | " | 510 | " |
@@ -791,9 +740,7 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
791 | 740 | ||
792 | #[test] | 741 | #[test] |
793 | fn test_hover_through_literal_string_in_macro() { | 742 | fn test_hover_through_literal_string_in_macro() { |
794 | // FIXME: Currently `hover::type_of` do not work inside | 743 | let hover_on = check_hover_result( |
795 | // macro expansion | ||
796 | check_hover_no_result( | ||
797 | r#" | 744 | r#" |
798 | //- /lib.rs | 745 | //- /lib.rs |
799 | macro_rules! arr { | 746 | macro_rules! arr { |
@@ -804,7 +751,10 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
804 | let _ = arr!("Tr<|>acks", &mastered_for_itunes); | 751 | let _ = arr!("Tr<|>acks", &mastered_for_itunes); |
805 | } | 752 | } |
806 | "#, | 753 | "#, |
754 | &["&str"], | ||
807 | ); | 755 | ); |
756 | |||
757 | assert_eq!(hover_on, "\"Tracks\""); | ||
808 | } | 758 | } |
809 | 759 | ||
810 | #[test] | 760 | #[test] |
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index d509de14e..f61028f78 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs | |||
@@ -455,11 +455,6 @@ impl Analysis { | |||
455 | self.with_db(|db| diagnostics::diagnostics(db, file_id)) | 455 | self.with_db(|db| diagnostics::diagnostics(db, file_id)) |
456 | } | 456 | } |
457 | 457 | ||
458 | /// Computes the type of the expression at the given position. | ||
459 | pub fn type_of(&self, frange: FileRange) -> Cancelable<Option<String>> { | ||
460 | self.with_db(|db| hover::type_of(db, frange)) | ||
461 | } | ||
462 | |||
463 | /// Returns the edit required to rename reference at the position to the new | 458 | /// Returns the edit required to rename reference at the position to the new |
464 | /// name. | 459 | /// name. |
465 | pub fn rename( | 460 | pub fn rename( |
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs index 06c92645e..4163a2cf5 100644 --- a/crates/ra_parser/src/grammar/expressions.rs +++ b/crates/ra_parser/src/grammar/expressions.rs | |||
@@ -169,6 +169,7 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) { | |||
169 | // let d: i32 = 92; | 169 | // let d: i32 = 92; |
170 | // let e: !; | 170 | // let e: !; |
171 | // let _: ! = {}; | 171 | // let _: ! = {}; |
172 | // let f = #[attr]||{}; | ||
172 | // } | 173 | // } |
173 | fn let_stmt(p: &mut Parser, m: Marker, with_semi: StmtWithSemi) { | 174 | fn let_stmt(p: &mut Parser, m: Marker, with_semi: StmtWithSemi) { |
174 | assert!(p.at(T![let])); | 175 | assert!(p.at(T![let])); |
@@ -178,7 +179,7 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) { | |||
178 | types::ascription(p); | 179 | types::ascription(p); |
179 | } | 180 | } |
180 | if p.eat(T![=]) { | 181 | if p.eat(T![=]) { |
181 | expressions::expr(p); | 182 | expressions::expr_with_attrs(p); |
182 | } | 183 | } |
183 | 184 | ||
184 | match with_semi { | 185 | match with_semi { |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0130_let_stmt.rs b/crates/ra_syntax/test_data/parser/inline/ok/0130_let_stmt.rs index 86803fe08..fa8ee49a2 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0130_let_stmt.rs +++ b/crates/ra_syntax/test_data/parser/inline/ok/0130_let_stmt.rs | |||
@@ -5,4 +5,5 @@ fn foo() { | |||
5 | let d: i32 = 92; | 5 | let d: i32 = 92; |
6 | let e: !; | 6 | let e: !; |
7 | let _: ! = {}; | 7 | let _: ! = {}; |
8 | let f = #[attr]||{}; | ||
8 | } | 9 | } |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0130_let_stmt.txt b/crates/ra_syntax/test_data/parser/inline/ok/0130_let_stmt.txt index 97166cfd5..17739dfbd 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0130_let_stmt.txt +++ b/crates/ra_syntax/test_data/parser/inline/ok/0130_let_stmt.txt | |||
@@ -1,5 +1,5 @@ | |||
1 | SOURCE_FILE@[0; 110) | 1 | SOURCE_FILE@[0; 135) |
2 | FN_DEF@[0; 109) | 2 | FN_DEF@[0; 134) |
3 | FN_KW@[0; 2) "fn" | 3 | FN_KW@[0; 2) "fn" |
4 | WHITESPACE@[2; 3) " " | 4 | WHITESPACE@[2; 3) " " |
5 | NAME@[3; 6) | 5 | NAME@[3; 6) |
@@ -8,8 +8,8 @@ SOURCE_FILE@[0; 110) | |||
8 | L_PAREN@[6; 7) "(" | 8 | L_PAREN@[6; 7) "(" |
9 | R_PAREN@[7; 8) ")" | 9 | R_PAREN@[7; 8) ")" |
10 | WHITESPACE@[8; 9) " " | 10 | WHITESPACE@[8; 9) " " |
11 | BLOCK_EXPR@[9; 109) | 11 | BLOCK_EXPR@[9; 134) |
12 | BLOCK@[9; 109) | 12 | BLOCK@[9; 134) |
13 | L_CURLY@[9; 10) "{" | 13 | L_CURLY@[9; 10) "{" |
14 | WHITESPACE@[10; 15) "\n " | 14 | WHITESPACE@[10; 15) "\n " |
15 | LET_STMT@[15; 21) | 15 | LET_STMT@[15; 21) |
@@ -97,6 +97,33 @@ SOURCE_FILE@[0; 110) | |||
97 | L_CURLY@[104; 105) "{" | 97 | L_CURLY@[104; 105) "{" |
98 | R_CURLY@[105; 106) "}" | 98 | R_CURLY@[105; 106) "}" |
99 | SEMI@[106; 107) ";" | 99 | SEMI@[106; 107) ";" |
100 | WHITESPACE@[107; 108) "\n" | 100 | WHITESPACE@[107; 112) "\n " |
101 | R_CURLY@[108; 109) "}" | 101 | LET_STMT@[112; 132) |
102 | WHITESPACE@[109; 110) "\n" | 102 | LET_KW@[112; 115) "let" |
103 | WHITESPACE@[115; 116) " " | ||
104 | BIND_PAT@[116; 117) | ||
105 | NAME@[116; 117) | ||
106 | IDENT@[116; 117) "f" | ||
107 | WHITESPACE@[117; 118) " " | ||
108 | EQ@[118; 119) "=" | ||
109 | WHITESPACE@[119; 120) " " | ||
110 | LAMBDA_EXPR@[120; 131) | ||
111 | ATTR@[120; 127) | ||
112 | POUND@[120; 121) "#" | ||
113 | L_BRACK@[121; 122) "[" | ||
114 | PATH@[122; 126) | ||
115 | PATH_SEGMENT@[122; 126) | ||
116 | NAME_REF@[122; 126) | ||
117 | IDENT@[122; 126) "attr" | ||
118 | R_BRACK@[126; 127) "]" | ||
119 | PARAM_LIST@[127; 129) | ||
120 | PIPE@[127; 128) "|" | ||
121 | PIPE@[128; 129) "|" | ||
122 | BLOCK_EXPR@[129; 131) | ||
123 | BLOCK@[129; 131) | ||
124 | L_CURLY@[129; 130) "{" | ||
125 | R_CURLY@[130; 131) "}" | ||
126 | SEMI@[131; 132) ";" | ||
127 | WHITESPACE@[132; 133) "\n" | ||
128 | R_CURLY@[133; 134) "}" | ||
129 | WHITESPACE@[134; 135) "\n" | ||