aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api/src')
-rw-r--r--crates/ra_ide_api/src/completion.rs2
-rw-r--r--crates/ra_ide_api/src/completion/complete_struct_literal.rs15
-rw-r--r--crates/ra_ide_api/src/completion/complete_struct_pattern.rs94
-rw-r--r--crates/ra_ide_api/src/completion/completion_context.rs15
-rw-r--r--crates/ra_ide_api/src/display/short_label.rs5
-rw-r--r--crates/ra_ide_api/src/extend_selection.rs16
-rw-r--r--crates/ra_ide_api/src/folding_ranges.rs18
-rw-r--r--crates/ra_ide_api/src/goto_type_definition.rs4
-rw-r--r--crates/ra_ide_api/src/join_lines.rs6
-rw-r--r--crates/ra_ide_api/src/matching_brace.rs6
-rw-r--r--crates/ra_ide_api/src/syntax_tree.rs6
-rw-r--r--crates/ra_ide_api/src/typing.rs15
12 files changed, 154 insertions, 48 deletions
diff --git a/crates/ra_ide_api/src/completion.rs b/crates/ra_ide_api/src/completion.rs
index c23b5da59..85160358a 100644
--- a/crates/ra_ide_api/src/completion.rs
+++ b/crates/ra_ide_api/src/completion.rs
@@ -4,6 +4,7 @@ mod presentation;
4 4
5mod complete_dot; 5mod complete_dot;
6mod complete_struct_literal; 6mod complete_struct_literal;
7mod complete_struct_pattern;
7mod complete_pattern; 8mod complete_pattern;
8mod complete_fn_param; 9mod complete_fn_param;
9mod complete_keyword; 10mod complete_keyword;
@@ -65,6 +66,7 @@ pub(crate) fn completions(db: &db::RootDatabase, position: FilePosition) -> Opti
65 complete_scope::complete_scope(&mut acc, &ctx); 66 complete_scope::complete_scope(&mut acc, &ctx);
66 complete_dot::complete_dot(&mut acc, &ctx); 67 complete_dot::complete_dot(&mut acc, &ctx);
67 complete_struct_literal::complete_struct_literal(&mut acc, &ctx); 68 complete_struct_literal::complete_struct_literal(&mut acc, &ctx);
69 complete_struct_pattern::complete_struct_pattern(&mut acc, &ctx);
68 complete_pattern::complete_pattern(&mut acc, &ctx); 70 complete_pattern::complete_pattern(&mut acc, &ctx);
69 complete_postfix::complete_postfix(&mut acc, &ctx); 71 complete_postfix::complete_postfix(&mut acc, &ctx);
70 Some(acc) 72 Some(acc)
diff --git a/crates/ra_ide_api/src/completion/complete_struct_literal.rs b/crates/ra_ide_api/src/completion/complete_struct_literal.rs
index 9410f740f..6aa41f498 100644
--- a/crates/ra_ide_api/src/completion/complete_struct_literal.rs
+++ b/crates/ra_ide_api/src/completion/complete_struct_literal.rs
@@ -1,23 +1,22 @@
1use hir::{Substs, Ty}; 1use hir::Substs;
2 2
3use crate::completion::{CompletionContext, Completions}; 3use crate::completion::{CompletionContext, Completions};
4 4
5/// Complete fields in fields literals. 5/// Complete fields in fields literals.
6pub(super) fn complete_struct_literal(acc: &mut Completions, ctx: &CompletionContext) { 6pub(super) fn complete_struct_literal(acc: &mut Completions, ctx: &CompletionContext) {
7 let (ty, variant) = match ctx.struct_lit_syntax.as_ref().and_then(|it| { 7 let (ty, variant) = match ctx.struct_lit_syntax.as_ref().and_then(|it| {
8 Some((ctx.analyzer.type_of(ctx.db, &it.clone().into())?, ctx.analyzer.resolve_variant(it)?)) 8 Some((
9 ctx.analyzer.type_of(ctx.db, &it.clone().into())?,
10 ctx.analyzer.resolve_struct_literal(it)?,
11 ))
9 }) { 12 }) {
10 Some(it) => it, 13 Some(it) => it,
11 _ => return, 14 _ => return,
12 }; 15 };
13 16 let substs = &ty.substs().unwrap_or_else(Substs::empty);
14 let ty_substs = match ty {
15 Ty::Apply(it) => it.parameters,
16 _ => Substs::empty(),
17 };
18 17
19 for field in variant.fields(ctx.db) { 18 for field in variant.fields(ctx.db) {
20 acc.add_field(ctx, field, &ty_substs); 19 acc.add_field(ctx, field, substs);
21 } 20 }
22} 21}
23 22
diff --git a/crates/ra_ide_api/src/completion/complete_struct_pattern.rs b/crates/ra_ide_api/src/completion/complete_struct_pattern.rs
new file mode 100644
index 000000000..d0dde5930
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/complete_struct_pattern.rs
@@ -0,0 +1,94 @@
1use hir::Substs;
2
3use crate::completion::{CompletionContext, Completions};
4
5pub(super) fn complete_struct_pattern(acc: &mut Completions, ctx: &CompletionContext) {
6 let (ty, variant) = match ctx.struct_lit_pat.as_ref().and_then(|it| {
7 Some((
8 ctx.analyzer.type_of_pat(ctx.db, &it.clone().into())?,
9 ctx.analyzer.resolve_struct_pattern(it)?,
10 ))
11 }) {
12 Some(it) => it,
13 _ => return,
14 };
15 let substs = &ty.substs().unwrap_or_else(Substs::empty);
16
17 for field in variant.fields(ctx.db) {
18 acc.add_field(ctx, field, substs);
19 }
20}
21
22#[cfg(test)]
23mod tests {
24 use crate::completion::{do_completion, CompletionItem, CompletionKind};
25 use insta::assert_debug_snapshot_matches;
26
27 fn complete(code: &str) -> Vec<CompletionItem> {
28 do_completion(code, CompletionKind::Reference)
29 }
30
31 #[test]
32 fn test_struct_pattern_field() {
33 let completions = complete(
34 r"
35 struct S { foo: u32 }
36
37 fn process(f: S) {
38 match f {
39 S { f<|>: 92 } => (),
40 }
41 }
42 ",
43 );
44 assert_debug_snapshot_matches!(completions, @r###"
45 ⋮[
46 ⋮ CompletionItem {
47 ⋮ label: "foo",
48 ⋮ source_range: [117; 118),
49 ⋮ delete: [117; 118),
50 ⋮ insert: "foo",
51 ⋮ kind: Field,
52 ⋮ detail: "u32",
53 ⋮ },
54 ⋮]
55 "###);
56 }
57
58 #[test]
59 fn test_struct_pattern_enum_variant() {
60 let completions = complete(
61 r"
62 enum E {
63 S { foo: u32, bar: () }
64 }
65
66 fn process(e: E) {
67 match e {
68 E::S { <|> } => (),
69 }
70 }
71 ",
72 );
73 assert_debug_snapshot_matches!(completions, @r###"
74 ⋮[
75 ⋮ CompletionItem {
76 ⋮ label: "bar",
77 ⋮ source_range: [161; 161),
78 ⋮ delete: [161; 161),
79 ⋮ insert: "bar",
80 ⋮ kind: Field,
81 ⋮ detail: "()",
82 ⋮ },
83 ⋮ CompletionItem {
84 ⋮ label: "foo",
85 ⋮ source_range: [161; 161),
86 ⋮ delete: [161; 161),
87 ⋮ insert: "foo",
88 ⋮ kind: Field,
89 ⋮ detail: "u32",
90 ⋮ },
91 ⋮]
92 "###);
93 }
94}
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs
index 2f78d5409..dfaa9ce69 100644
--- a/crates/ra_ide_api/src/completion/completion_context.rs
+++ b/crates/ra_ide_api/src/completion/completion_context.rs
@@ -1,6 +1,6 @@
1use hir::source_binder; 1use hir::source_binder;
2use ra_syntax::{ 2use ra_syntax::{
3 algo::{find_covering_element, find_node_at_offset, find_token_at_offset}, 3 algo::{find_covering_element, find_node_at_offset},
4 ast, AstNode, Parse, SourceFile, 4 ast, AstNode, Parse, SourceFile,
5 SyntaxKind::*, 5 SyntaxKind::*,
6 SyntaxNode, SyntaxToken, TextRange, TextUnit, 6 SyntaxNode, SyntaxToken, TextRange, TextUnit,
@@ -21,6 +21,7 @@ pub(crate) struct CompletionContext<'a> {
21 pub(super) function_syntax: Option<ast::FnDef>, 21 pub(super) function_syntax: Option<ast::FnDef>,
22 pub(super) use_item_syntax: Option<ast::UseItem>, 22 pub(super) use_item_syntax: Option<ast::UseItem>,
23 pub(super) struct_lit_syntax: Option<ast::StructLit>, 23 pub(super) struct_lit_syntax: Option<ast::StructLit>,
24 pub(super) struct_lit_pat: Option<ast::StructPat>,
24 pub(super) is_param: bool, 25 pub(super) is_param: bool,
25 /// If a name-binding or reference to a const in a pattern. 26 /// If a name-binding or reference to a const in a pattern.
26 /// Irrefutable patterns (like let) are excluded. 27 /// Irrefutable patterns (like let) are excluded.
@@ -48,7 +49,7 @@ impl<'a> CompletionContext<'a> {
48 ) -> Option<CompletionContext<'a>> { 49 ) -> Option<CompletionContext<'a>> {
49 let module = source_binder::module_from_position(db, position); 50 let module = source_binder::module_from_position(db, position);
50 let token = 51 let token =
51 find_token_at_offset(original_parse.tree().syntax(), position.offset).left_biased()?; 52 original_parse.tree().syntax().token_at_offset(position.offset).left_biased()?;
52 let analyzer = 53 let analyzer =
53 hir::SourceAnalyzer::new(db, position.file_id, &token.parent(), Some(position.offset)); 54 hir::SourceAnalyzer::new(db, position.file_id, &token.parent(), Some(position.offset));
54 let mut ctx = CompletionContext { 55 let mut ctx = CompletionContext {
@@ -60,6 +61,7 @@ impl<'a> CompletionContext<'a> {
60 function_syntax: None, 61 function_syntax: None,
61 use_item_syntax: None, 62 use_item_syntax: None,
62 struct_lit_syntax: None, 63 struct_lit_syntax: None,
64 struct_lit_pat: None,
63 is_param: false, 65 is_param: false,
64 is_pat_binding: false, 66 is_pat_binding: false,
65 is_trivial_path: false, 67 is_trivial_path: false,
@@ -106,8 +108,7 @@ impl<'a> CompletionContext<'a> {
106 // Otherwise, see if this is a declaration. We can use heuristics to 108 // Otherwise, see if this is a declaration. We can use heuristics to
107 // suggest declaration names, see `CompletionKind::Magic`. 109 // suggest declaration names, see `CompletionKind::Magic`.
108 if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), offset) { 110 if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), offset) {
109 if is_node::<ast::BindPat>(name.syntax()) { 111 if let Some(bind_pat) = name.syntax().ancestors().find_map(ast::BindPat::cast) {
110 let bind_pat = name.syntax().ancestors().find_map(ast::BindPat::cast).unwrap();
111 let parent = bind_pat.syntax().parent(); 112 let parent = bind_pat.syntax().parent();
112 if parent.clone().and_then(ast::MatchArm::cast).is_some() 113 if parent.clone().and_then(ast::MatchArm::cast).is_some()
113 || parent.and_then(ast::Condition::cast).is_some() 114 || parent.and_then(ast::Condition::cast).is_some()
@@ -119,6 +120,10 @@ impl<'a> CompletionContext<'a> {
119 self.is_param = true; 120 self.is_param = true;
120 return; 121 return;
121 } 122 }
123 if name.syntax().ancestors().find_map(ast::FieldPatList::cast).is_some() {
124 self.struct_lit_pat =
125 find_node_at_offset(original_parse.tree().syntax(), self.offset);
126 }
122 } 127 }
123 } 128 }
124 129
@@ -235,7 +240,7 @@ fn find_node_with_range<N: AstNode>(syntax: &SyntaxNode, range: TextRange) -> Op
235} 240}
236 241
237fn is_node<N: AstNode>(node: &SyntaxNode) -> bool { 242fn is_node<N: AstNode>(node: &SyntaxNode) -> bool {
238 match node.ancestors().filter_map(N::cast).next() { 243 match node.ancestors().find_map(N::cast) {
239 None => false, 244 None => false,
240 Some(n) => n.syntax().text_range() == node.text_range(), 245 Some(n) => n.syntax().text_range() == node.text_range(),
241 } 246 }
diff --git a/crates/ra_ide_api/src/display/short_label.rs b/crates/ra_ide_api/src/display/short_label.rs
index be499e485..825a033ee 100644
--- a/crates/ra_ide_api/src/display/short_label.rs
+++ b/crates/ra_ide_api/src/display/short_label.rs
@@ -1,5 +1,4 @@
1use std::fmt::Write; 1use format_buf::format;
2
3use ra_syntax::ast::{self, AstNode, NameOwner, TypeAscriptionOwner, VisibilityOwner}; 2use ra_syntax::ast::{self, AstNode, NameOwner, TypeAscriptionOwner, VisibilityOwner};
4 3
5pub(crate) trait ShortLabel { 4pub(crate) trait ShortLabel {
@@ -73,7 +72,7 @@ where
73 let mut buf = short_label_from_node(node, prefix)?; 72 let mut buf = short_label_from_node(node, prefix)?;
74 73
75 if let Some(type_ref) = node.ascribed_type() { 74 if let Some(type_ref) = node.ascribed_type() {
76 write!(buf, ": {}", type_ref.syntax()).unwrap(); 75 format!(buf, ": {}", type_ref.syntax());
77 } 76 }
78 77
79 Some(buf) 78 Some(buf)
diff --git a/crates/ra_ide_api/src/extend_selection.rs b/crates/ra_ide_api/src/extend_selection.rs
index 140820df6..edbf622c1 100644
--- a/crates/ra_ide_api/src/extend_selection.rs
+++ b/crates/ra_ide_api/src/extend_selection.rs
@@ -1,10 +1,10 @@
1use ra_db::SourceDatabase; 1use ra_db::SourceDatabase;
2use ra_syntax::{ 2use ra_syntax::{
3 algo::{find_covering_element, find_token_at_offset, TokenAtOffset}, 3 algo::find_covering_element,
4 ast::{self, AstNode, AstToken}, 4 ast::{self, AstNode, AstToken},
5 Direction, SyntaxElement, 5 Direction, NodeOrToken,
6 SyntaxKind::*, 6 SyntaxKind::*,
7 SyntaxNode, SyntaxToken, TextRange, TextUnit, T, 7 SyntaxNode, SyntaxToken, TextRange, TextUnit, TokenAtOffset, T,
8}; 8};
9 9
10use crate::{db::RootDatabase, FileRange}; 10use crate::{db::RootDatabase, FileRange};
@@ -34,7 +34,7 @@ fn try_extend_selection(root: &SyntaxNode, range: TextRange) -> Option<TextRange
34 34
35 if range.is_empty() { 35 if range.is_empty() {
36 let offset = range.start(); 36 let offset = range.start();
37 let mut leaves = find_token_at_offset(root, offset); 37 let mut leaves = root.token_at_offset(offset);
38 if leaves.clone().all(|it| it.kind() == WHITESPACE) { 38 if leaves.clone().all(|it| it.kind() == WHITESPACE) {
39 return Some(extend_ws(root, leaves.next()?, offset)); 39 return Some(extend_ws(root, leaves.next()?, offset));
40 } 40 }
@@ -53,7 +53,7 @@ fn try_extend_selection(root: &SyntaxNode, range: TextRange) -> Option<TextRange
53 return Some(leaf_range); 53 return Some(leaf_range);
54 }; 54 };
55 let node = match find_covering_element(root, range) { 55 let node = match find_covering_element(root, range) {
56 SyntaxElement::Token(token) => { 56 NodeOrToken::Token(token) => {
57 if token.text_range() != range { 57 if token.text_range() != range {
58 return Some(token.text_range()); 58 return Some(token.text_range());
59 } 59 }
@@ -64,7 +64,7 @@ fn try_extend_selection(root: &SyntaxNode, range: TextRange) -> Option<TextRange
64 } 64 }
65 token.parent() 65 token.parent()
66 } 66 }
67 SyntaxElement::Node(node) => node, 67 NodeOrToken::Node(node) => node,
68 }; 68 };
69 if node.text_range() != range { 69 if node.text_range() != range {
70 return Some(node.text_range()); 70 return Some(node.text_range());
@@ -153,8 +153,8 @@ fn extend_list_item(node: &SyntaxNode) -> Option<TextRange> {
153 node.siblings_with_tokens(dir) 153 node.siblings_with_tokens(dir)
154 .skip(1) 154 .skip(1)
155 .skip_while(|node| match node { 155 .skip_while(|node| match node {
156 SyntaxElement::Node(_) => false, 156 NodeOrToken::Node(_) => false,
157 SyntaxElement::Token(it) => is_single_line_ws(it), 157 NodeOrToken::Token(it) => is_single_line_ws(it),
158 }) 158 })
159 .next() 159 .next()
160 .and_then(|it| it.into_token()) 160 .and_then(|it| it.into_token())
diff --git a/crates/ra_ide_api/src/folding_ranges.rs b/crates/ra_ide_api/src/folding_ranges.rs
index 571d1c595..e60ae8cf6 100644
--- a/crates/ra_ide_api/src/folding_ranges.rs
+++ b/crates/ra_ide_api/src/folding_ranges.rs
@@ -2,7 +2,7 @@ use rustc_hash::FxHashSet;
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 ast::{self, AstNode, AstToken, VisibilityOwner}, 4 ast::{self, AstNode, AstToken, VisibilityOwner},
5 Direction, SourceFile, SyntaxElement, 5 Direction, NodeOrToken, SourceFile,
6 SyntaxKind::{self, *}, 6 SyntaxKind::{self, *},
7 SyntaxNode, TextRange, 7 SyntaxNode, TextRange,
8}; 8};
@@ -31,8 +31,8 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
31 // Fold items that span multiple lines 31 // Fold items that span multiple lines
32 if let Some(kind) = fold_kind(element.kind()) { 32 if let Some(kind) = fold_kind(element.kind()) {
33 let is_multiline = match &element { 33 let is_multiline = match &element {
34 SyntaxElement::Node(node) => node.text().contains_char('\n'), 34 NodeOrToken::Node(node) => node.text().contains_char('\n'),
35 SyntaxElement::Token(token) => token.text().contains('\n'), 35 NodeOrToken::Token(token) => token.text().contains('\n'),
36 }; 36 };
37 if is_multiline { 37 if is_multiline {
38 res.push(Fold { range: element.text_range(), kind }); 38 res.push(Fold { range: element.text_range(), kind });
@@ -41,7 +41,7 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
41 } 41 }
42 42
43 match element { 43 match element {
44 SyntaxElement::Token(token) => { 44 NodeOrToken::Token(token) => {
45 // Fold groups of comments 45 // Fold groups of comments
46 if let Some(comment) = ast::Comment::cast(token) { 46 if let Some(comment) = ast::Comment::cast(token) {
47 if !visited_comments.contains(&comment) { 47 if !visited_comments.contains(&comment) {
@@ -53,7 +53,7 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
53 } 53 }
54 } 54 }
55 } 55 }
56 SyntaxElement::Node(node) => { 56 NodeOrToken::Node(node) => {
57 // Fold groups of imports 57 // Fold groups of imports
58 if node.kind() == USE_ITEM && !visited_imports.contains(&node) { 58 if node.kind() == USE_ITEM && !visited_imports.contains(&node) {
59 if let Some(range) = contiguous_range_for_group(&node, &mut visited_imports) { 59 if let Some(range) = contiguous_range_for_group(&node, &mut visited_imports) {
@@ -108,7 +108,7 @@ fn contiguous_range_for_group_unless(
108 let mut last = first.clone(); 108 let mut last = first.clone();
109 for element in first.siblings_with_tokens(Direction::Next) { 109 for element in first.siblings_with_tokens(Direction::Next) {
110 let node = match element { 110 let node = match element {
111 SyntaxElement::Token(token) => { 111 NodeOrToken::Token(token) => {
112 if let Some(ws) = ast::Whitespace::cast(token) { 112 if let Some(ws) = ast::Whitespace::cast(token) {
113 if !ws.spans_multiple_lines() { 113 if !ws.spans_multiple_lines() {
114 // Ignore whitespace without blank lines 114 // Ignore whitespace without blank lines
@@ -119,7 +119,7 @@ fn contiguous_range_for_group_unless(
119 // group ends here 119 // group ends here
120 break; 120 break;
121 } 121 }
122 SyntaxElement::Node(node) => node, 122 NodeOrToken::Node(node) => node,
123 }; 123 };
124 124
125 // Stop if we find a node that doesn't belong to the group 125 // Stop if we find a node that doesn't belong to the group
@@ -154,7 +154,7 @@ fn contiguous_range_for_comment(
154 let mut last = first.clone(); 154 let mut last = first.clone();
155 for element in first.syntax().siblings_with_tokens(Direction::Next) { 155 for element in first.syntax().siblings_with_tokens(Direction::Next) {
156 match element { 156 match element {
157 SyntaxElement::Token(token) => { 157 NodeOrToken::Token(token) => {
158 if let Some(ws) = ast::Whitespace::cast(token.clone()) { 158 if let Some(ws) = ast::Whitespace::cast(token.clone()) {
159 if !ws.spans_multiple_lines() { 159 if !ws.spans_multiple_lines() {
160 // Ignore whitespace without blank lines 160 // Ignore whitespace without blank lines
@@ -173,7 +173,7 @@ fn contiguous_range_for_comment(
173 // * A comment of a different flavor was reached 173 // * A comment of a different flavor was reached
174 break; 174 break;
175 } 175 }
176 SyntaxElement::Node(_) => break, 176 NodeOrToken::Node(_) => break,
177 }; 177 };
178 } 178 }
179 179
diff --git a/crates/ra_ide_api/src/goto_type_definition.rs b/crates/ra_ide_api/src/goto_type_definition.rs
index 007259d9e..72884e5ca 100644
--- a/crates/ra_ide_api/src/goto_type_definition.rs
+++ b/crates/ra_ide_api/src/goto_type_definition.rs
@@ -1,5 +1,5 @@
1use ra_db::SourceDatabase; 1use ra_db::SourceDatabase;
2use ra_syntax::{algo::find_token_at_offset, ast, AstNode}; 2use ra_syntax::{ast, AstNode};
3 3
4use crate::{db::RootDatabase, FilePosition, NavigationTarget, RangeInfo}; 4use crate::{db::RootDatabase, FilePosition, NavigationTarget, RangeInfo};
5 5
@@ -9,7 +9,7 @@ pub(crate) fn goto_type_definition(
9) -> Option<RangeInfo<Vec<NavigationTarget>>> { 9) -> Option<RangeInfo<Vec<NavigationTarget>>> {
10 let parse = db.parse(position.file_id); 10 let parse = db.parse(position.file_id);
11 11
12 let node = find_token_at_offset(parse.tree().syntax(), position.offset).find_map(|token| { 12 let node = parse.tree().syntax().token_at_offset(position.offset).find_map(|token| {
13 token 13 token
14 .parent() 14 .parent()
15 .ancestors() 15 .ancestors()
diff --git a/crates/ra_ide_api/src/join_lines.rs b/crates/ra_ide_api/src/join_lines.rs
index 7f25f2108..a2e4b6f3c 100644
--- a/crates/ra_ide_api/src/join_lines.rs
+++ b/crates/ra_ide_api/src/join_lines.rs
@@ -3,7 +3,7 @@ use ra_fmt::{compute_ws, extract_trivial_expression};
3use ra_syntax::{ 3use ra_syntax::{
4 algo::{find_covering_element, non_trivia_sibling}, 4 algo::{find_covering_element, non_trivia_sibling},
5 ast::{self, AstNode, AstToken}, 5 ast::{self, AstNode, AstToken},
6 Direction, SourceFile, SyntaxElement, 6 Direction, NodeOrToken, SourceFile,
7 SyntaxKind::{self, WHITESPACE}, 7 SyntaxKind::{self, WHITESPACE},
8 SyntaxNode, SyntaxToken, TextRange, TextUnit, T, 8 SyntaxNode, SyntaxToken, TextRange, TextUnit, T,
9}; 9};
@@ -23,8 +23,8 @@ pub fn join_lines(file: &SourceFile, range: TextRange) -> TextEdit {
23 }; 23 };
24 24
25 let node = match find_covering_element(file.syntax(), range) { 25 let node = match find_covering_element(file.syntax(), range) {
26 SyntaxElement::Node(node) => node, 26 NodeOrToken::Node(node) => node,
27 SyntaxElement::Token(token) => token.parent(), 27 NodeOrToken::Token(token) => token.parent(),
28 }; 28 };
29 let mut edit = TextEditBuilder::default(); 29 let mut edit = TextEditBuilder::default();
30 for token in node.descendants_with_tokens().filter_map(|it| it.into_token()) { 30 for token in node.descendants_with_tokens().filter_map(|it| it.into_token()) {
diff --git a/crates/ra_ide_api/src/matching_brace.rs b/crates/ra_ide_api/src/matching_brace.rs
index 1e2fac848..e802d01e4 100644
--- a/crates/ra_ide_api/src/matching_brace.rs
+++ b/crates/ra_ide_api/src/matching_brace.rs
@@ -1,9 +1,11 @@
1use ra_syntax::{algo::find_token_at_offset, ast::AstNode, SourceFile, SyntaxKind, TextUnit, T}; 1use ra_syntax::{ast::AstNode, SourceFile, SyntaxKind, TextUnit, T};
2 2
3pub fn matching_brace(file: &SourceFile, offset: TextUnit) -> Option<TextUnit> { 3pub fn matching_brace(file: &SourceFile, offset: TextUnit) -> Option<TextUnit> {
4 const BRACES: &[SyntaxKind] = 4 const BRACES: &[SyntaxKind] =
5 &[T!['{'], T!['}'], T!['['], T![']'], T!['('], T![')'], T![<], T![>]]; 5 &[T!['{'], T!['}'], T!['['], T![']'], T!['('], T![')'], T![<], T![>]];
6 let (brace_node, brace_idx) = find_token_at_offset(file.syntax(), offset) 6 let (brace_node, brace_idx) = file
7 .syntax()
8 .token_at_offset(offset)
7 .filter_map(|node| { 9 .filter_map(|node| {
8 let idx = BRACES.iter().position(|&brace| brace == node.kind())?; 10 let idx = BRACES.iter().position(|&brace| brace == node.kind())?;
9 Some((node, idx)) 11 Some((node, idx))
diff --git a/crates/ra_ide_api/src/syntax_tree.rs b/crates/ra_ide_api/src/syntax_tree.rs
index 76c50f6d6..a07e670fa 100644
--- a/crates/ra_ide_api/src/syntax_tree.rs
+++ b/crates/ra_ide_api/src/syntax_tree.rs
@@ -1,7 +1,7 @@
1use crate::db::RootDatabase; 1use crate::db::RootDatabase;
2use ra_db::SourceDatabase; 2use ra_db::SourceDatabase;
3use ra_syntax::{ 3use ra_syntax::{
4 algo, AstNode, SourceFile, SyntaxElement, 4 algo, AstNode, NodeOrToken, SourceFile,
5 SyntaxKind::{RAW_STRING, STRING}, 5 SyntaxKind::{RAW_STRING, STRING},
6 SyntaxToken, TextRange, 6 SyntaxToken, TextRange,
7}; 7};
@@ -16,8 +16,8 @@ pub(crate) fn syntax_tree(
16 let parse = db.parse(file_id); 16 let parse = db.parse(file_id);
17 if let Some(text_range) = text_range { 17 if let Some(text_range) = text_range {
18 let node = match algo::find_covering_element(parse.tree().syntax(), text_range) { 18 let node = match algo::find_covering_element(parse.tree().syntax(), text_range) {
19 SyntaxElement::Node(node) => node, 19 NodeOrToken::Node(node) => node,
20 SyntaxElement::Token(token) => { 20 NodeOrToken::Token(token) => {
21 if let Some(tree) = syntax_tree_for_string(&token, text_range) { 21 if let Some(tree) = syntax_tree_for_string(&token, text_range) {
22 return tree; 22 return tree;
23 } 23 }
diff --git a/crates/ra_ide_api/src/typing.rs b/crates/ra_ide_api/src/typing.rs
index 5a1cbcc49..6b3fd5904 100644
--- a/crates/ra_ide_api/src/typing.rs
+++ b/crates/ra_ide_api/src/typing.rs
@@ -1,11 +1,11 @@
1use ra_db::{FilePosition, SourceDatabase}; 1use ra_db::{FilePosition, SourceDatabase};
2use ra_fmt::leading_indent; 2use ra_fmt::leading_indent;
3use ra_syntax::{ 3use ra_syntax::{
4 algo::{find_node_at_offset, find_token_at_offset, TokenAtOffset}, 4 algo::find_node_at_offset,
5 ast::{self, AstToken}, 5 ast::{self, AstToken},
6 AstNode, SmolStr, SourceFile, 6 AstNode, SmolStr, SourceFile,
7 SyntaxKind::*, 7 SyntaxKind::*,
8 SyntaxToken, TextRange, TextUnit, 8 SyntaxToken, TextRange, TextUnit, TokenAtOffset,
9}; 9};
10use ra_text_edit::{TextEdit, TextEditBuilder}; 10use ra_text_edit::{TextEdit, TextEditBuilder};
11 11
@@ -14,7 +14,9 @@ use crate::{db::RootDatabase, SourceChange, SourceFileEdit};
14pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<SourceChange> { 14pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<SourceChange> {
15 let parse = db.parse(position.file_id); 15 let parse = db.parse(position.file_id);
16 let file = parse.tree(); 16 let file = parse.tree();
17 let comment = find_token_at_offset(file.syntax(), position.offset) 17 let comment = file
18 .syntax()
19 .token_at_offset(position.offset)
18 .left_biased() 20 .left_biased()
19 .and_then(ast::Comment::cast)?; 21 .and_then(ast::Comment::cast)?;
20 22
@@ -45,7 +47,7 @@ pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<Sour
45} 47}
46 48
47fn node_indent(file: &SourceFile, token: &SyntaxToken) -> Option<SmolStr> { 49fn node_indent(file: &SourceFile, token: &SyntaxToken) -> Option<SmolStr> {
48 let ws = match find_token_at_offset(file.syntax(), token.text_range().start()) { 50 let ws = match file.syntax().token_at_offset(token.text_range().start()) {
49 TokenAtOffset::Between(l, r) => { 51 TokenAtOffset::Between(l, r) => {
50 assert!(r == *token); 52 assert!(r == *token);
51 l 53 l
@@ -91,7 +93,10 @@ pub(crate) fn on_dot_typed(db: &RootDatabase, position: FilePosition) -> Option<
91 let parse = db.parse(position.file_id); 93 let parse = db.parse(position.file_id);
92 assert_eq!(parse.tree().syntax().text().char_at(position.offset), Some('.')); 94 assert_eq!(parse.tree().syntax().text().char_at(position.offset), Some('.'));
93 95
94 let whitespace = find_token_at_offset(parse.tree().syntax(), position.offset) 96 let whitespace = parse
97 .tree()
98 .syntax()
99 .token_at_offset(position.offset)
95 .left_biased() 100 .left_biased()
96 .and_then(ast::Whitespace::cast)?; 101 .and_then(ast::Whitespace::cast)?;
97 102