diff options
author | Edwin Cheng <[email protected]> | 2020-02-26 16:12:26 +0000 |
---|---|---|
committer | Edwin Cheng <[email protected]> | 2020-02-26 16:12:26 +0000 |
commit | 553254973e24a2c0bdf1475fccbbc4603e8421f0 (patch) | |
tree | a97feb3e004489c7b9896ba753a891cc7c07a8e0 /crates/ra_ide/src | |
parent | 2dee0779e9977e4570122c42ac35c4183bb8e604 (diff) |
Skip trival token in original_range
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r-- | crates/ra_ide/src/extend_selection.rs | 24 | ||||
-rw-r--r-- | crates/ra_ide/src/hover.rs | 27 |
2 files changed, 34 insertions, 17 deletions
diff --git a/crates/ra_ide/src/extend_selection.rs b/crates/ra_ide/src/extend_selection.rs index 86e6f12d7..2e09bd1ec 100644 --- a/crates/ra_ide/src/extend_selection.rs +++ b/crates/ra_ide/src/extend_selection.rs | |||
@@ -5,7 +5,7 @@ use std::iter::successors; | |||
5 | use hir::Semantics; | 5 | use hir::Semantics; |
6 | use ra_ide_db::RootDatabase; | 6 | use ra_ide_db::RootDatabase; |
7 | use ra_syntax::{ | 7 | use ra_syntax::{ |
8 | algo::{self, find_covering_element}, | 8 | algo::{self, find_covering_element, skip_trivia_token}, |
9 | ast::{self, AstNode, AstToken}, | 9 | ast::{self, AstNode, AstToken}, |
10 | Direction, NodeOrToken, | 10 | Direction, NodeOrToken, |
11 | SyntaxKind::{self, *}, | 11 | SyntaxKind::{self, *}, |
@@ -118,14 +118,14 @@ fn extend_tokens_from_range( | |||
118 | NodeOrToken::Token(it) => (it.clone(), it), | 118 | NodeOrToken::Token(it) => (it.clone(), it), |
119 | }; | 119 | }; |
120 | 120 | ||
121 | let mut first_token = skip_whitespace(first_token, Direction::Next)?; | 121 | let mut first_token = skip_trivia_token(first_token, Direction::Next)?; |
122 | let mut last_token = skip_whitespace(last_token, Direction::Prev)?; | 122 | let mut last_token = skip_trivia_token(last_token, Direction::Prev)?; |
123 | 123 | ||
124 | while !first_token.text_range().is_subrange(&original_range) { | 124 | while !first_token.text_range().is_subrange(&original_range) { |
125 | first_token = skip_whitespace(first_token.next_token()?, Direction::Next)?; | 125 | first_token = skip_trivia_token(first_token.next_token()?, Direction::Next)?; |
126 | } | 126 | } |
127 | while !last_token.text_range().is_subrange(&original_range) { | 127 | while !last_token.text_range().is_subrange(&original_range) { |
128 | last_token = skip_whitespace(last_token.prev_token()?, Direction::Prev)?; | 128 | last_token = skip_trivia_token(last_token.prev_token()?, Direction::Prev)?; |
129 | } | 129 | } |
130 | 130 | ||
131 | // compute original mapped token range | 131 | // compute original mapped token range |
@@ -149,14 +149,14 @@ fn extend_tokens_from_range( | |||
149 | // Find the first and last text range under expanded parent | 149 | // Find the first and last text range under expanded parent |
150 | let first = successors(Some(first_token), |token| { | 150 | let first = successors(Some(first_token), |token| { |
151 | let token = token.prev_token()?; | 151 | let token = token.prev_token()?; |
152 | skip_whitespace(token, Direction::Prev) | 152 | skip_trivia_token(token, Direction::Prev) |
153 | }) | 153 | }) |
154 | .take_while(validate) | 154 | .take_while(validate) |
155 | .last()?; | 155 | .last()?; |
156 | 156 | ||
157 | let last = successors(Some(last_token), |token| { | 157 | let last = successors(Some(last_token), |token| { |
158 | let token = token.next_token()?; | 158 | let token = token.next_token()?; |
159 | skip_whitespace(token, Direction::Next) | 159 | skip_trivia_token(token, Direction::Next) |
160 | }) | 160 | }) |
161 | .take_while(validate) | 161 | .take_while(validate) |
162 | .last()?; | 162 | .last()?; |
@@ -169,16 +169,6 @@ fn extend_tokens_from_range( | |||
169 | } | 169 | } |
170 | } | 170 | } |
171 | 171 | ||
172 | fn skip_whitespace(mut token: SyntaxToken, direction: Direction) -> Option<SyntaxToken> { | ||
173 | while token.kind() == WHITESPACE { | ||
174 | token = match direction { | ||
175 | Direction::Next => token.next_token()?, | ||
176 | Direction::Prev => token.prev_token()?, | ||
177 | } | ||
178 | } | ||
179 | Some(token) | ||
180 | } | ||
181 | |||
182 | fn union_range(range: TextRange, r: TextRange) -> TextRange { | 172 | fn union_range(range: TextRange, r: TextRange) -> TextRange { |
183 | let start = range.start().min(r.start()); | 173 | let start = range.start().min(r.start()); |
184 | let end = range.end().max(r.end()); | 174 | let end = range.end().max(r.end()); |
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index 29b16e602..177038e20 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs | |||
@@ -174,6 +174,10 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn | |||
174 | .ancestors() | 174 | .ancestors() |
175 | .find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some())?; | 175 | .find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some())?; |
176 | 176 | ||
177 | // FIXME: Currently `hover::typeof` do not work inside | ||
178 | // macro expansion such that if the hover range is pointing to | ||
179 | // a string literal, the following type_of will return None. | ||
180 | // See also `test_hover_through_literal_string_in_macro` | ||
177 | let frange = sema.original_range(&node); | 181 | let frange = sema.original_range(&node); |
178 | res.extend(type_of(db, frange).map(rust_code_markup)); | 182 | res.extend(type_of(db, frange).map(rust_code_markup)); |
179 | if res.is_empty() { | 183 | if res.is_empty() { |
@@ -250,6 +254,11 @@ mod tests { | |||
250 | content[hover.range].to_string() | 254 | content[hover.range].to_string() |
251 | } | 255 | } |
252 | 256 | ||
257 | fn check_hover_no_result(fixture: &str) { | ||
258 | let (analysis, position) = analysis_and_position(fixture); | ||
259 | assert!(analysis.hover(position).unwrap().is_none()); | ||
260 | } | ||
261 | |||
253 | #[test] | 262 | #[test] |
254 | fn hover_shows_type_of_an_expression() { | 263 | fn hover_shows_type_of_an_expression() { |
255 | let (analysis, position) = single_file_with_position( | 264 | let (analysis, position) = single_file_with_position( |
@@ -775,6 +784,24 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
775 | } | 784 | } |
776 | 785 | ||
777 | #[test] | 786 | #[test] |
787 | fn test_hover_through_literal_string_in_macro() { | ||
788 | // FIXME: Currently `hover::type_of` do not work inside | ||
789 | // macro expansion | ||
790 | check_hover_no_result( | ||
791 | r#" | ||
792 | //- /lib.rs | ||
793 | macro_rules! arr { | ||
794 | ($($tt:tt)*) => { [$($tt)*)] } | ||
795 | } | ||
796 | fn foo() { | ||
797 | let mastered_for_itunes = ""; | ||
798 | let _ = arr!("Tr<|>acks", &mastered_for_itunes); | ||
799 | } | ||
800 | "#, | ||
801 | ); | ||
802 | } | ||
803 | |||
804 | #[test] | ||
778 | fn test_hover_non_ascii_space_doc() { | 805 | fn test_hover_non_ascii_space_doc() { |
779 | check_hover_result( | 806 | check_hover_result( |
780 | " | 807 | " |