aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_assists/src/handlers/change_visibility.rs13
-rw-r--r--crates/ra_ide/src/hover.rs98
-rw-r--r--crates/ra_ide/src/lib.rs5
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs3
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0130_let_stmt.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0130_let_stmt.txt41
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
31fn add_vis(ctx: AssistCtx) -> Option<Assist> { 31fn 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};
8use ra_syntax::{ 8use 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::{
16use crate::{ 15use 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
209pub(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)]
229mod tests { 211mod 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 @@
1SOURCE_FILE@[0; 110) 1SOURCE_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"