aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_assists/src/add_derive.rs6
-rw-r--r--crates/ra_assists/src/add_explicit_type.rs4
-rw-r--r--crates/ra_assists/src/add_impl.rs4
-rw-r--r--crates/ra_assists/src/add_missing_impl_members.rs4
-rw-r--r--crates/ra_assists/src/assist_ctx.rs2
-rw-r--r--crates/ra_assists/src/ast_editor.rs5
-rw-r--r--crates/ra_assists/src/auto_import.rs18
-rw-r--r--crates/ra_assists/src/change_visibility.rs23
-rw-r--r--crates/ra_assists/src/fill_match_arms.rs4
-rw-r--r--crates/ra_assists/src/flip_binexpr.rs6
-rw-r--r--crates/ra_assists/src/flip_comma.rs6
-rw-r--r--crates/ra_assists/src/inline_local_variable.rs7
-rw-r--r--crates/ra_assists/src/introduce_variable.rs12
-rw-r--r--crates/ra_assists/src/move_guard.rs20
-rw-r--r--crates/ra_assists/src/remove_dbg.rs4
-rw-r--r--crates/ra_assists/src/replace_if_let_with_match.rs4
-rw-r--r--crates/ra_assists/src/split_import.rs8
-rw-r--r--crates/ra_cli/src/analysis_stats.rs2
-rw-r--r--crates/ra_cli/src/main.rs2
-rw-r--r--crates/ra_hir/src/expr.rs2
-rw-r--r--crates/ra_hir/src/expr/scope.rs2
-rw-r--r--crates/ra_hir/src/source_binder.rs2
-rw-r--r--crates/ra_hir/src/ty/tests.rs2
-rw-r--r--crates/ra_ide_api/src/call_info.rs4
-rw-r--r--crates/ra_ide_api/src/completion/complete_keyword.rs2
-rw-r--r--crates/ra_ide_api/src/completion/complete_path.rs2
-rw-r--r--crates/ra_ide_api/src/completion/complete_postfix.rs2
-rw-r--r--crates/ra_ide_api/src/completion/completion_context.rs32
-rw-r--r--crates/ra_ide_api/src/diagnostics.rs12
-rw-r--r--crates/ra_ide_api/src/display/navigation_target.rs6
-rw-r--r--crates/ra_ide_api/src/display/structure.rs8
-rw-r--r--crates/ra_ide_api/src/extend_selection.rs48
-rw-r--r--crates/ra_ide_api/src/folding_ranges.rs9
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs4
-rw-r--r--crates/ra_ide_api/src/goto_type_definition.rs2
-rw-r--r--crates/ra_ide_api/src/hover.rs10
-rw-r--r--crates/ra_ide_api/src/impls.rs4
-rw-r--r--crates/ra_ide_api/src/join_lines.rs22
-rw-r--r--crates/ra_ide_api/src/matching_brace.rs2
-rw-r--r--crates/ra_ide_api/src/references.rs2
-rw-r--r--crates/ra_ide_api/src/runnables.rs4
-rw-r--r--crates/ra_ide_api/src/symbol_index.rs2
-rw-r--r--crates/ra_ide_api/src/syntax_highlighting.rs14
-rw-r--r--crates/ra_ide_api/src/syntax_tree.rs8
-rw-r--r--crates/ra_ide_api/src/typing.rs8
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs6
-rw-r--r--crates/ra_mbe/src/tests.rs8
-rw-r--r--crates/ra_syntax/src/algo.rs2
-rw-r--r--crates/ra_syntax/src/fuzz.rs8
-rw-r--r--crates/ra_syntax/src/lib.rs4
-rw-r--r--crates/ra_syntax/src/parsing/reparsing.rs16
-rw-r--r--crates/ra_syntax/src/ptr.rs6
-rw-r--r--crates/ra_syntax/src/syntax_node.rs68
-rw-r--r--crates/ra_syntax/src/syntax_text.rs8
-rw-r--r--crates/ra_syntax/src/validation.rs12
-rw-r--r--crates/ra_syntax/src/validation/block.rs5
-rw-r--r--crates/ra_syntax/src/validation/field_expr.rs2
57 files changed, 260 insertions, 241 deletions
diff --git a/crates/ra_assists/src/add_derive.rs b/crates/ra_assists/src/add_derive.rs
index f19196f53..9c88644df 100644
--- a/crates/ra_assists/src/add_derive.rs
+++ b/crates/ra_assists/src/add_derive.rs
@@ -22,9 +22,9 @@ pub(crate) fn add_derive(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist>
22 edit.insert(node_start, "#[derive()]\n"); 22 edit.insert(node_start, "#[derive()]\n");
23 node_start + TextUnit::of_str("#[derive(") 23 node_start + TextUnit::of_str("#[derive(")
24 } 24 }
25 Some(tt) => tt.syntax().range().end() - TextUnit::of_char(')'), 25 Some(tt) => tt.syntax().text_range().end() - TextUnit::of_char(')'),
26 }; 26 };
27 edit.target(nominal.syntax().range()); 27 edit.target(nominal.syntax().text_range());
28 edit.set_cursor(offset) 28 edit.set_cursor(offset)
29 }); 29 });
30 30
@@ -37,7 +37,7 @@ fn derive_insertion_offset(nominal: &ast::NominalDef) -> Option<TextUnit> {
37 .syntax() 37 .syntax()
38 .children_with_tokens() 38 .children_with_tokens()
39 .find(|it| it.kind() != COMMENT && it.kind() != WHITESPACE)?; 39 .find(|it| it.kind() != COMMENT && it.kind() != WHITESPACE)?;
40 Some(non_ws_child.range().start()) 40 Some(non_ws_child.text_range().start())
41} 41}
42 42
43#[cfg(test)] 43#[cfg(test)]
diff --git a/crates/ra_assists/src/add_explicit_type.rs b/crates/ra_assists/src/add_explicit_type.rs
index a69cfc8e3..88970929f 100644
--- a/crates/ra_assists/src/add_explicit_type.rs
+++ b/crates/ra_assists/src/add_explicit_type.rs
@@ -16,10 +16,10 @@ pub(crate) fn add_explicit_type(mut ctx: AssistCtx<impl HirDatabase>) -> Option<
16 PatKind::BindPat(bind_pat) => bind_pat, 16 PatKind::BindPat(bind_pat) => bind_pat,
17 _ => return None, 17 _ => return None,
18 }; 18 };
19 let pat_range = pat.syntax().range(); 19 let pat_range = pat.syntax().text_range();
20 // The binding must have a name 20 // The binding must have a name
21 let name = pat.name()?; 21 let name = pat.name()?;
22 let name_range = name.syntax().range(); 22 let name_range = name.syntax().text_range();
23 // Assist not applicable if the type has already been specified 23 // Assist not applicable if the type has already been specified
24 if stmt.syntax().children_with_tokens().any(|child| child.kind() == T![:]) { 24 if stmt.syntax().children_with_tokens().any(|child| child.kind() == T![:]) {
25 return None; 25 return None;
diff --git a/crates/ra_assists/src/add_impl.rs b/crates/ra_assists/src/add_impl.rs
index cebc19539..9a0cfb4e7 100644
--- a/crates/ra_assists/src/add_impl.rs
+++ b/crates/ra_assists/src/add_impl.rs
@@ -11,9 +11,9 @@ pub(crate) fn add_impl(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
11 let nominal = ctx.node_at_offset::<ast::NominalDef>()?; 11 let nominal = ctx.node_at_offset::<ast::NominalDef>()?;
12 let name = nominal.name()?; 12 let name = nominal.name()?;
13 ctx.add_action(AssistId("add_impl"), "add impl", |edit| { 13 ctx.add_action(AssistId("add_impl"), "add impl", |edit| {
14 edit.target(nominal.syntax().range()); 14 edit.target(nominal.syntax().text_range());
15 let type_params = nominal.type_param_list(); 15 let type_params = nominal.type_param_list();
16 let start_offset = nominal.syntax().range().end(); 16 let start_offset = nominal.syntax().text_range().end();
17 let mut buf = String::new(); 17 let mut buf = String::new();
18 buf.push_str("\n\nimpl"); 18 buf.push_str("\n\nimpl");
19 if let Some(type_params) = &type_params { 19 if let Some(type_params) = &type_params {
diff --git a/crates/ra_assists/src/add_missing_impl_members.rs b/crates/ra_assists/src/add_missing_impl_members.rs
index b992a4dc8..995e44d5e 100644
--- a/crates/ra_assists/src/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/add_missing_impl_members.rs
@@ -43,7 +43,7 @@ fn add_missing_impl_members_inner(
43 43
44 let trait_def = { 44 let trait_def = {
45 let file_id = ctx.frange.file_id; 45 let file_id = ctx.frange.file_id;
46 let position = FilePosition { file_id, offset: impl_node.syntax().range().start() }; 46 let position = FilePosition { file_id, offset: impl_node.syntax().text_range().start() };
47 let analyzer = hir::SourceAnalyzer::new(ctx.db, position.file_id, impl_node.syntax(), None); 47 let analyzer = hir::SourceAnalyzer::new(ctx.db, position.file_id, impl_node.syntax(), None);
48 48
49 resolve_target_trait_def(ctx.db, &analyzer, &impl_node)? 49 resolve_target_trait_def(ctx.db, &analyzer, &impl_node)?
@@ -87,7 +87,7 @@ fn add_missing_impl_members_inner(
87 ast_editor.append_items(items); 87 ast_editor.append_items(items);
88 88
89 let first_new_item = ast_editor.ast().impl_items().nth(n_existing_items).unwrap(); 89 let first_new_item = ast_editor.ast().impl_items().nth(n_existing_items).unwrap();
90 let cursor_position = first_new_item.syntax().range().start(); 90 let cursor_position = first_new_item.syntax().text_range().start();
91 ast_editor.into_text_edit(edit.text_edit_builder()); 91 ast_editor.into_text_edit(edit.text_edit_builder());
92 92
93 edit.set_cursor(cursor_position); 93 edit.set_cursor(cursor_position);
diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs
index e52085f85..4d5a76de6 100644
--- a/crates/ra_assists/src/assist_ctx.rs
+++ b/crates/ra_assists/src/assist_ctx.rs
@@ -141,7 +141,7 @@ impl AssistBuilder {
141 if let Some(indent) = leading_indent(node) { 141 if let Some(indent) = leading_indent(node) {
142 replace_with = reindent(&replace_with, &indent) 142 replace_with = reindent(&replace_with, &indent)
143 } 143 }
144 self.replace(node.range(), replace_with) 144 self.replace(node.text_range(), replace_with)
145 } 145 }
146 146
147 pub(crate) fn set_edit_builder(&mut self, edit: TextEditBuilder) { 147 pub(crate) fn set_edit_builder(&mut self, edit: TextEditBuilder) {
diff --git a/crates/ra_assists/src/ast_editor.rs b/crates/ra_assists/src/ast_editor.rs
index a35334d7e..36235eb13 100644
--- a/crates/ra_assists/src/ast_editor.rs
+++ b/crates/ra_assists/src/ast_editor.rs
@@ -22,7 +22,10 @@ impl<N: AstNode> AstEditor<N> {
22 // FIXME: compute a more fine-grained diff here. 22 // FIXME: compute a more fine-grained diff here.
23 // If *you* know a nice algorithm to compute diff between two syntax 23 // If *you* know a nice algorithm to compute diff between two syntax
24 // tree, tell me about it! 24 // tree, tell me about it!
25 builder.replace(self.original_ast.syntax().range(), self.ast().syntax().text().to_string()); 25 builder.replace(
26 self.original_ast.syntax().text_range(),
27 self.ast().syntax().text().to_string(),
28 );
26 } 29 }
27 30
28 pub fn ast(&self) -> &N { 31 pub fn ast(&self) -> &N {
diff --git a/crates/ra_assists/src/auto_import.rs b/crates/ra_assists/src/auto_import.rs
index 0eb4bdb62..43e75eee1 100644
--- a/crates/ra_assists/src/auto_import.rs
+++ b/crates/ra_assists/src/auto_import.rs
@@ -356,7 +356,7 @@ fn best_action_for_target(
356 // todo: we should include even whitespace blocks as anchor candidates 356 // todo: we should include even whitespace blocks as anchor candidates
357 let anchor = container 357 let anchor = container
358 .children() 358 .children()
359 .find(|n| n.range().start() < anchor.range().start()) 359 .find(|n| n.text_range().start() < anchor.text_range().start())
360 .or_else(|| Some(anchor)); 360 .or_else(|| Some(anchor));
361 361
362 ImportAction::add_new_use(anchor, false) 362 ImportAction::add_new_use(anchor, false)
@@ -418,7 +418,7 @@ fn make_assist_add_new_use(
418 buf.push_str(&spaces); 418 buf.push_str(&spaces);
419 } 419 }
420 } 420 }
421 let position = if after { anchor.range().end() } else { anchor.range().start() }; 421 let position = if after { anchor.text_range().end() } else { anchor.text_range().start() };
422 edit.insert(position, buf); 422 edit.insert(position, buf);
423 } 423 }
424} 424}
@@ -434,10 +434,10 @@ fn make_assist_add_in_tree_list(
434 let mut buf = String::new(); 434 let mut buf = String::new();
435 let comma = last.syntax().siblings(Direction::Next).find(|n| n.kind() == T![,]); 435 let comma = last.syntax().siblings(Direction::Next).find(|n| n.kind() == T![,]);
436 let offset = if let Some(comma) = comma { 436 let offset = if let Some(comma) = comma {
437 comma.range().end() 437 comma.text_range().end()
438 } else { 438 } else {
439 buf.push_str(","); 439 buf.push_str(",");
440 last.syntax().range().end() 440 last.syntax().text_range().end()
441 }; 441 };
442 if add_self { 442 if add_self {
443 buf.push_str(" self") 443 buf.push_str(" self")
@@ -462,11 +462,11 @@ fn make_assist_add_nested_import(
462 if let Some(use_tree) = use_tree { 462 if let Some(use_tree) = use_tree {
463 let (start, add_colon_colon) = if let Some(first_segment_to_split) = first_segment_to_split 463 let (start, add_colon_colon) = if let Some(first_segment_to_split) = first_segment_to_split
464 { 464 {
465 (first_segment_to_split.syntax().range().start(), false) 465 (first_segment_to_split.syntax().text_range().start(), false)
466 } else { 466 } else {
467 (use_tree.syntax().range().end(), true) 467 (use_tree.syntax().text_range().end(), true)
468 }; 468 };
469 let end = use_tree.syntax().range().end(); 469 let end = use_tree.syntax().text_range().end();
470 470
471 let mut buf = String::new(); 471 let mut buf = String::new();
472 if add_colon_colon { 472 if add_colon_colon {
@@ -497,8 +497,8 @@ fn apply_auto_import(
497 // Here we are assuming the assist will provide a correct use statement 497 // Here we are assuming the assist will provide a correct use statement
498 // so we can delete the path qualifier 498 // so we can delete the path qualifier
499 edit.delete(TextRange::from_to( 499 edit.delete(TextRange::from_to(
500 path.syntax().range().start(), 500 path.syntax().text_range().start(),
501 last.syntax().range().start(), 501 last.syntax().text_range().start(),
502 )); 502 ));
503 } 503 }
504} 504}
diff --git a/crates/ra_assists/src/change_visibility.rs b/crates/ra_assists/src/change_visibility.rs
index ab10d2aa4..d28cdd07b 100644
--- a/crates/ra_assists/src/change_visibility.rs
+++ b/crates/ra_assists/src/change_visibility.rs
@@ -35,14 +35,15 @@ fn add_vis(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
35 if parent.children().any(|child| child.kind() == VISIBILITY) { 35 if parent.children().any(|child| child.kind() == VISIBILITY) {
36 return None; 36 return None;
37 } 37 }
38 (vis_offset(&parent), keyword.range()) 38 (vis_offset(&parent), keyword.text_range())
39 } else { 39 } else {
40 let ident = ctx.token_at_offset().find(|leaf| leaf.kind() == IDENT)?; 40 let ident = ctx.token_at_offset().find(|leaf| leaf.kind() == IDENT)?;
41 let field = ident.parent().ancestors().find_map(ast::NamedFieldDef::cast)?; 41 let field = ident.parent().ancestors().find_map(ast::NamedFieldDef::cast)?;
42 if field.name()?.syntax().range() != ident.range() && field.visibility().is_some() { 42 if field.name()?.syntax().text_range() != ident.text_range() && field.visibility().is_some()
43 {
43 return None; 44 return None;
44 } 45 }
45 (vis_offset(field.syntax()), ident.range()) 46 (vis_offset(field.syntax()), ident.text_range())
46 }; 47 };
47 48
48 ctx.add_action(AssistId("change_visibility"), "make pub(crate)", |edit| { 49 ctx.add_action(AssistId("change_visibility"), "make pub(crate)", |edit| {
@@ -61,25 +62,25 @@ fn vis_offset(node: &SyntaxNode) -> TextUnit {
61 _ => false, 62 _ => false,
62 }) 63 })
63 .next() 64 .next()
64 .map(|it| it.range().start()) 65 .map(|it| it.text_range().start())
65 .unwrap_or_else(|| node.range().start()) 66 .unwrap_or_else(|| node.text_range().start())
66} 67}
67 68
68fn change_vis(mut ctx: AssistCtx<impl HirDatabase>, vis: ast::Visibility) -> Option<Assist> { 69fn change_vis(mut ctx: AssistCtx<impl HirDatabase>, vis: ast::Visibility) -> Option<Assist> {
69 if vis.syntax().text() == "pub" { 70 if vis.syntax().text() == "pub" {
70 ctx.add_action(AssistId("change_visibility"), "change to pub(crate)", |edit| { 71 ctx.add_action(AssistId("change_visibility"), "change to pub(crate)", |edit| {
71 edit.target(vis.syntax().range()); 72 edit.target(vis.syntax().text_range());
72 edit.replace(vis.syntax().range(), "pub(crate)"); 73 edit.replace(vis.syntax().text_range(), "pub(crate)");
73 edit.set_cursor(vis.syntax().range().start()) 74 edit.set_cursor(vis.syntax().text_range().start())
74 }); 75 });
75 76
76 return ctx.build(); 77 return ctx.build();
77 } 78 }
78 if vis.syntax().text() == "pub(crate)" { 79 if vis.syntax().text() == "pub(crate)" {
79 ctx.add_action(AssistId("change_visibility"), "change to pub", |edit| { 80 ctx.add_action(AssistId("change_visibility"), "change to pub", |edit| {
80 edit.target(vis.syntax().range()); 81 edit.target(vis.syntax().text_range());
81 edit.replace(vis.syntax().range(), "pub"); 82 edit.replace(vis.syntax().text_range(), "pub");
82 edit.set_cursor(vis.syntax().range().start()); 83 edit.set_cursor(vis.syntax().text_range().start());
83 }); 84 });
84 85
85 return ctx.build(); 86 return ctx.build();
diff --git a/crates/ra_assists/src/fill_match_arms.rs b/crates/ra_assists/src/fill_match_arms.rs
index b96806ac6..939429892 100644
--- a/crates/ra_assists/src/fill_match_arms.rs
+++ b/crates/ra_assists/src/fill_match_arms.rs
@@ -84,8 +84,8 @@ pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<As
84 buf.push_str(" => (),\n"); 84 buf.push_str(" => (),\n");
85 } 85 }
86 buf.push_str("}"); 86 buf.push_str("}");
87 edit.target(match_expr.syntax().range()); 87 edit.target(match_expr.syntax().text_range());
88 edit.set_cursor(expr.syntax().range().start()); 88 edit.set_cursor(expr.syntax().text_range().start());
89 edit.replace_node_and_indent(match_expr.syntax(), buf); 89 edit.replace_node_and_indent(match_expr.syntax(), buf);
90 }); 90 });
91 91
diff --git a/crates/ra_assists/src/flip_binexpr.rs b/crates/ra_assists/src/flip_binexpr.rs
index 2e591ad3b..b55b36a8e 100644
--- a/crates/ra_assists/src/flip_binexpr.rs
+++ b/crates/ra_assists/src/flip_binexpr.rs
@@ -8,7 +8,7 @@ pub(crate) fn flip_binexpr(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assis
8 let expr = ctx.node_at_offset::<BinExpr>()?; 8 let expr = ctx.node_at_offset::<BinExpr>()?;
9 let lhs = expr.lhs()?.syntax().clone(); 9 let lhs = expr.lhs()?.syntax().clone();
10 let rhs = expr.rhs()?.syntax().clone(); 10 let rhs = expr.rhs()?.syntax().clone();
11 let op_range = expr.op_token()?.range(); 11 let op_range = expr.op_token()?.text_range();
12 // The assist should be applied only if the cursor is on the operator 12 // The assist should be applied only if the cursor is on the operator
13 let cursor_in_range = ctx.frange.range.is_subrange(&op_range); 13 let cursor_in_range = ctx.frange.range.is_subrange(&op_range);
14 if !cursor_in_range { 14 if !cursor_in_range {
@@ -25,8 +25,8 @@ pub(crate) fn flip_binexpr(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assis
25 if let FlipAction::FlipAndReplaceOp(new_op) = action { 25 if let FlipAction::FlipAndReplaceOp(new_op) = action {
26 edit.replace(op_range, new_op); 26 edit.replace(op_range, new_op);
27 } 27 }
28 edit.replace(lhs.range(), rhs.text()); 28 edit.replace(lhs.text_range(), rhs.text());
29 edit.replace(rhs.range(), lhs.text()); 29 edit.replace(rhs.text_range(), lhs.text());
30 }); 30 });
31 31
32 ctx.build() 32 ctx.build()
diff --git a/crates/ra_assists/src/flip_comma.rs b/crates/ra_assists/src/flip_comma.rs
index 13016ae06..34489329c 100644
--- a/crates/ra_assists/src/flip_comma.rs
+++ b/crates/ra_assists/src/flip_comma.rs
@@ -8,9 +8,9 @@ pub(crate) fn flip_comma(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist>
8 let prev = non_trivia_sibling(comma.clone().into(), Direction::Prev)?; 8 let prev = non_trivia_sibling(comma.clone().into(), Direction::Prev)?;
9 let next = non_trivia_sibling(comma.clone().into(), Direction::Next)?; 9 let next = non_trivia_sibling(comma.clone().into(), Direction::Next)?;
10 ctx.add_action(AssistId("flip_comma"), "flip comma", |edit| { 10 ctx.add_action(AssistId("flip_comma"), "flip comma", |edit| {
11 edit.target(comma.range()); 11 edit.target(comma.text_range());
12 edit.replace(prev.range(), next.to_string()); 12 edit.replace(prev.text_range(), next.to_string());
13 edit.replace(next.range(), prev.to_string()); 13 edit.replace(next.text_range(), prev.to_string());
14 }); 14 });
15 15
16 ctx.build() 16 ctx.build()
diff --git a/crates/ra_assists/src/inline_local_variable.rs b/crates/ra_assists/src/inline_local_variable.rs
index 3c17089de..82c4d54b0 100644
--- a/crates/ra_assists/src/inline_local_variable.rs
+++ b/crates/ra_assists/src/inline_local_variable.rs
@@ -22,9 +22,12 @@ pub(crate) fn inline_local_varialbe(mut ctx: AssistCtx<impl HirDatabase>) -> Opt
22 .next_sibling_or_token() 22 .next_sibling_or_token()
23 .and_then(|it| ast::Whitespace::cast(it.as_token()?.clone())) 23 .and_then(|it| ast::Whitespace::cast(it.as_token()?.clone()))
24 { 24 {
25 TextRange::from_to(let_stmt.syntax().range().start(), whitespace.syntax().range().end()) 25 TextRange::from_to(
26 let_stmt.syntax().text_range().start(),
27 whitespace.syntax().text_range().end(),
28 )
26 } else { 29 } else {
27 let_stmt.syntax().range() 30 let_stmt.syntax().text_range()
28 }; 31 };
29 let analyzer = hir::SourceAnalyzer::new(ctx.db, ctx.frange.file_id, bind_pat.syntax(), None); 32 let analyzer = hir::SourceAnalyzer::new(ctx.db, ctx.frange.file_id, bind_pat.syntax(), None);
30 let refs = analyzer.find_all_refs(&bind_pat); 33 let refs = analyzer.find_all_refs(&bind_pat);
diff --git a/crates/ra_assists/src/introduce_variable.rs b/crates/ra_assists/src/introduce_variable.rs
index ce28132c9..df6c58989 100644
--- a/crates/ra_assists/src/introduce_variable.rs
+++ b/crates/ra_assists/src/introduce_variable.rs
@@ -48,7 +48,7 @@ pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option
48 if !full_stmt.unwrap().has_semi() { 48 if !full_stmt.unwrap().has_semi() {
49 buf.push_str(";"); 49 buf.push_str(";");
50 } 50 }
51 edit.replace(expr.syntax().range(), buf); 51 edit.replace(expr.syntax().text_range(), buf);
52 } else { 52 } else {
53 buf.push_str(";"); 53 buf.push_str(";");
54 54
@@ -66,14 +66,14 @@ pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option
66 buf.push_str(text); 66 buf.push_str(text);
67 } 67 }
68 68
69 edit.target(expr.syntax().range()); 69 edit.target(expr.syntax().text_range());
70 edit.replace(expr.syntax().range(), "var_name".to_string()); 70 edit.replace(expr.syntax().text_range(), "var_name".to_string());
71 edit.insert(anchor_stmt.range().start(), buf); 71 edit.insert(anchor_stmt.text_range().start(), buf);
72 if wrap_in_block { 72 if wrap_in_block {
73 edit.insert(anchor_stmt.range().end(), " }"); 73 edit.insert(anchor_stmt.text_range().end(), " }");
74 } 74 }
75 } 75 }
76 edit.set_cursor(anchor_stmt.range().start() + cursor_offset); 76 edit.set_cursor(anchor_stmt.text_range().start() + cursor_offset);
77 }); 77 });
78 78
79 ctx.build() 79 ctx.build()
diff --git a/crates/ra_assists/src/move_guard.rs b/crates/ra_assists/src/move_guard.rs
index 313c9ad18..0f3cdbe53 100644
--- a/crates/ra_assists/src/move_guard.rs
+++ b/crates/ra_assists/src/move_guard.rs
@@ -17,11 +17,11 @@ pub(crate) fn move_guard_to_arm_body(mut ctx: AssistCtx<impl HirDatabase>) -> Op
17 let buf = format!("if {} {{ {} }}", guard_conditions.syntax().text(), arm_expr.syntax().text()); 17 let buf = format!("if {} {{ {} }}", guard_conditions.syntax().text(), arm_expr.syntax().text());
18 18
19 ctx.add_action(AssistId("move_guard_to_arm_body"), "move guard to arm body", |edit| { 19 ctx.add_action(AssistId("move_guard_to_arm_body"), "move guard to arm body", |edit| {
20 edit.target(guard.syntax().range()); 20 edit.target(guard.syntax().text_range());
21 let offseting_amount = match &space_before_guard { 21 let offseting_amount = match &space_before_guard {
22 Some(SyntaxElement::Token(tok)) => { 22 Some(SyntaxElement::Token(tok)) => {
23 if let Some(_) = ast::Whitespace::cast(tok.clone()) { 23 if let Some(_) = ast::Whitespace::cast(tok.clone()) {
24 let ele = space_before_guard.unwrap().range(); 24 let ele = space_before_guard.unwrap().text_range();
25 edit.delete(ele); 25 edit.delete(ele);
26 ele.len() 26 ele.len()
27 } else { 27 } else {
@@ -31,9 +31,11 @@ pub(crate) fn move_guard_to_arm_body(mut ctx: AssistCtx<impl HirDatabase>) -> Op
31 _ => TextUnit::from(0), 31 _ => TextUnit::from(0),
32 }; 32 };
33 33
34 edit.delete(guard.syntax().range()); 34 edit.delete(guard.syntax().text_range());
35 edit.replace_node_and_indent(arm_expr.syntax(), buf); 35 edit.replace_node_and_indent(arm_expr.syntax(), buf);
36 edit.set_cursor(arm_expr.syntax().range().start() + TextUnit::from(3) - offseting_amount); 36 edit.set_cursor(
37 arm_expr.syntax().text_range().start() + TextUnit::from(3) - offseting_amount,
38 );
37 }); 39 });
38 ctx.build() 40 ctx.build()
39} 41}
@@ -62,18 +64,18 @@ pub(crate) fn move_arm_cond_to_match_guard(mut ctx: AssistCtx<impl HirDatabase>)
62 AssistId("move_arm_cond_to_match_guard"), 64 AssistId("move_arm_cond_to_match_guard"),
63 "move condition to match guard", 65 "move condition to match guard",
64 |edit| { 66 |edit| {
65 edit.target(if_expr.syntax().range()); 67 edit.target(if_expr.syntax().text_range());
66 let then_only_expr = then_block.statements().next().is_none(); 68 let then_only_expr = then_block.statements().next().is_none();
67 69
68 match &then_block.expr() { 70 match &then_block.expr() {
69 Some(then_expr) if then_only_expr => { 71 Some(then_expr) if then_only_expr => {
70 edit.replace(if_expr.syntax().range(), then_expr.syntax().text()) 72 edit.replace(if_expr.syntax().text_range(), then_expr.syntax().text())
71 } 73 }
72 _ => edit.replace(if_expr.syntax().range(), then_block.syntax().text()), 74 _ => edit.replace(if_expr.syntax().text_range(), then_block.syntax().text()),
73 } 75 }
74 76
75 edit.insert(last_match_pat.syntax().range().end(), buf); 77 edit.insert(last_match_pat.syntax().text_range().end(), buf);
76 edit.set_cursor(last_match_pat.syntax().range().end() + TextUnit::from(1)); 78 edit.set_cursor(last_match_pat.syntax().text_range().end() + TextUnit::from(1));
77 }, 79 },
78 ); 80 );
79 ctx.build() 81 ctx.build()
diff --git a/crates/ra_assists/src/remove_dbg.rs b/crates/ra_assists/src/remove_dbg.rs
index 5657ee4b8..870133fda 100644
--- a/crates/ra_assists/src/remove_dbg.rs
+++ b/crates/ra_assists/src/remove_dbg.rs
@@ -12,7 +12,7 @@ pub(crate) fn remove_dbg(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist>
12 return None; 12 return None;
13 } 13 }
14 14
15 let macro_range = macro_call.syntax().range(); 15 let macro_range = macro_call.syntax().text_range();
16 16
17 // If the cursor is inside the macro call, we'll try to maintain the cursor 17 // If the cursor is inside the macro call, we'll try to maintain the cursor
18 // position by subtracting the length of dbg!( from the start of the file 18 // position by subtracting the length of dbg!( from the start of the file
@@ -43,7 +43,7 @@ pub(crate) fn remove_dbg(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist>
43 }; 43 };
44 44
45 ctx.add_action(AssistId("remove_dbg"), "remove dbg!()", |edit| { 45 ctx.add_action(AssistId("remove_dbg"), "remove dbg!()", |edit| {
46 edit.target(macro_call.syntax().range()); 46 edit.target(macro_call.syntax().text_range());
47 edit.replace(macro_range, macro_content); 47 edit.replace(macro_range, macro_content);
48 edit.set_cursor(cursor_pos); 48 edit.set_cursor(cursor_pos);
49 }); 49 });
diff --git a/crates/ra_assists/src/replace_if_let_with_match.rs b/crates/ra_assists/src/replace_if_let_with_match.rs
index 5de6aa266..c0bf6d235 100644
--- a/crates/ra_assists/src/replace_if_let_with_match.rs
+++ b/crates/ra_assists/src/replace_if_let_with_match.rs
@@ -17,9 +17,9 @@ pub(crate) fn replace_if_let_with_match(mut ctx: AssistCtx<impl HirDatabase>) ->
17 17
18 ctx.add_action(AssistId("replace_if_let_with_match"), "replace with match", |edit| { 18 ctx.add_action(AssistId("replace_if_let_with_match"), "replace with match", |edit| {
19 let match_expr = build_match_expr(expr, pat, then_block, else_block); 19 let match_expr = build_match_expr(expr, pat, then_block, else_block);
20 edit.target(if_expr.syntax().range()); 20 edit.target(if_expr.syntax().text_range());
21 edit.replace_node_and_indent(if_expr.syntax(), match_expr); 21 edit.replace_node_and_indent(if_expr.syntax(), match_expr);
22 edit.set_cursor(if_expr.syntax().range().start()) 22 edit.set_cursor(if_expr.syntax().text_range().start())
23 }); 23 });
24 24
25 ctx.build() 25 ctx.build()
diff --git a/crates/ra_assists/src/split_import.rs b/crates/ra_assists/src/split_import.rs
index a8feb67c8..2c1edddb9 100644
--- a/crates/ra_assists/src/split_import.rs
+++ b/crates/ra_assists/src/split_import.rs
@@ -15,14 +15,14 @@ pub(crate) fn split_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assis
15 return None; 15 return None;
16 } 16 }
17 17
18 let l_curly = colon_colon.range().end(); 18 let l_curly = colon_colon.text_range().end();
19 let r_curly = match top_path.syntax().parent().and_then(ast::UseTree::cast) { 19 let r_curly = match top_path.syntax().parent().and_then(ast::UseTree::cast) {
20 Some(tree) => tree.syntax().range().end(), 20 Some(tree) => tree.syntax().text_range().end(),
21 None => top_path.syntax().range().end(), 21 None => top_path.syntax().text_range().end(),
22 }; 22 };
23 23
24 ctx.add_action(AssistId("split_import"), "split import", |edit| { 24 ctx.add_action(AssistId("split_import"), "split import", |edit| {
25 edit.target(colon_colon.range()); 25 edit.target(colon_colon.text_range());
26 edit.insert(l_curly, "{"); 26 edit.insert(l_curly, "{");
27 edit.insert(r_curly, "}"); 27 edit.insert(r_curly, "}");
28 edit.set_cursor(l_curly + TextUnit::of_str("{")); 28 edit.set_cursor(l_curly + TextUnit::of_str("{"));
diff --git a/crates/ra_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs
index c2a2b66d5..403aab352 100644
--- a/crates/ra_cli/src/analysis_stats.rs
+++ b/crates/ra_cli/src/analysis_stats.rs
@@ -70,7 +70,7 @@ pub fn run(verbose: bool, memory_usage: bool, path: &Path, only: Option<&str>) -
70 let src = f.source(db); 70 let src = f.source(db);
71 let original_file = src.file_id.original_file(db); 71 let original_file = src.file_id.original_file(db);
72 let path = db.file_relative_path(original_file); 72 let path = db.file_relative_path(original_file);
73 let syntax_range = src.ast.syntax().range(); 73 let syntax_range = src.ast.syntax().text_range();
74 write!(msg, " ({:?} {})", path, syntax_range).unwrap(); 74 write!(msg, " ({:?} {})", path, syntax_range).unwrap();
75 } 75 }
76 bar.set_message(&msg); 76 bar.set_message(&msg);
diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs
index 375e2f508..de8191ca3 100644
--- a/crates/ra_cli/src/main.rs
+++ b/crates/ra_cli/src/main.rs
@@ -55,7 +55,7 @@ fn main() -> Result<()> {
55 let _p = profile("parsing"); 55 let _p = profile("parsing");
56 let file = file()?; 56 let file = file()?;
57 if !matches.is_present("no-dump") { 57 if !matches.is_present("no-dump") {
58 println!("{}", file.syntax().debug_dump()); 58 println!("{:#?}", file.syntax());
59 } 59 }
60 std::mem::forget(file); 60 std::mem::forget(file);
61 } 61 }
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 66cb9633b..6eed67f50 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -843,7 +843,7 @@ where
843 let file_id = call_id.as_file(MacroFileKind::Expr); 843 let file_id = call_id.as_file(MacroFileKind::Expr);
844 if let Some(node) = self.db.parse_or_expand(file_id) { 844 if let Some(node) = self.db.parse_or_expand(file_id) {
845 if let Some(expr) = ast::Expr::cast(node) { 845 if let Some(expr) = ast::Expr::cast(node) {
846 log::debug!("macro expansion {}", expr.syntax().debug_dump()); 846 log::debug!("macro expansion {:#?}", expr.syntax());
847 let old_file_id = 847 let old_file_id =
848 std::mem::replace(&mut self.current_file_id, file_id); 848 std::mem::replace(&mut self.current_file_id, file_id);
849 let id = self.collect_expr(expr); 849 let id = self.collect_expr(expr);
diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs
index 6589b782c..79e1857f9 100644
--- a/crates/ra_hir/src/expr/scope.rs
+++ b/crates/ra_hir/src/expr/scope.rs
@@ -296,7 +296,7 @@ mod tests {
296 let local_name_entry = analyzer.resolve_local_name(&name_ref).unwrap(); 296 let local_name_entry = analyzer.resolve_local_name(&name_ref).unwrap();
297 let local_name = 297 let local_name =
298 local_name_entry.ptr().either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); 298 local_name_entry.ptr().either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr());
299 assert_eq!(local_name.range(), expected_name.syntax().range()); 299 assert_eq!(local_name.range(), expected_name.syntax().text_range());
300 } 300 }
301 301
302 #[test] 302 #[test]
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index df67d2c39..4c173a4f7 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -361,7 +361,7 @@ impl SourceAnalyzer {
361 }) 361 })
362 .map(|name_ref| ReferenceDescriptor { 362 .map(|name_ref| ReferenceDescriptor {
363 name: name_ref.text().to_string(), 363 name: name_ref.text().to_string(),
364 range: name_ref.syntax().range(), 364 range: name_ref.syntax().text_range(),
365 }) 365 })
366 .collect() 366 .collect()
367 } 367 }
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 265740e54..7b2bdeb3f 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -3127,7 +3127,7 @@ fn infer(content: &str) -> String {
3127 for (syntax_ptr, ty) in &types { 3127 for (syntax_ptr, ty) in &types {
3128 let node = syntax_ptr.to_node(source_file.syntax()); 3128 let node = syntax_ptr.to_node(source_file.syntax());
3129 let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) { 3129 let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) {
3130 (self_param.self_kw_token().range(), "self".to_string()) 3130 (self_param.self_kw_token().text_range(), "self".to_string())
3131 } else { 3131 } else {
3132 (syntax_ptr.range(), node.text().to_string().replace("\n", " ")) 3132 (syntax_ptr.range(), node.text().to_string().replace("\n", " "))
3133 }; 3133 };
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs
index 270499612..212448d41 100644
--- a/crates/ra_ide_api/src/call_info.rs
+++ b/crates/ra_ide_api/src/call_info.rs
@@ -47,7 +47,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
47 // Number of arguments specified at the call site 47 // Number of arguments specified at the call site
48 let num_args_at_callsite = arg_list.args().count(); 48 let num_args_at_callsite = arg_list.args().count();
49 49
50 let arg_list_range = arg_list.syntax().range(); 50 let arg_list_range = arg_list.syntax().text_range();
51 if !arg_list_range.contains_inclusive(position.offset) { 51 if !arg_list_range.contains_inclusive(position.offset) {
52 tested_by!(call_info_bad_offset); 52 tested_by!(call_info_bad_offset);
53 return None; 53 return None;
@@ -57,7 +57,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
57 num_args_at_callsite, 57 num_args_at_callsite,
58 arg_list 58 arg_list
59 .args() 59 .args()
60 .take_while(|arg| arg.syntax().range().end() < position.offset) 60 .take_while(|arg| arg.syntax().text_range().end() < position.offset)
61 .count(), 61 .count(),
62 ); 62 );
63 63
diff --git a/crates/ra_ide_api/src/completion/complete_keyword.rs b/crates/ra_ide_api/src/completion/complete_keyword.rs
index 4cf34eff8..18c1839dc 100644
--- a/crates/ra_ide_api/src/completion/complete_keyword.rs
+++ b/crates/ra_ide_api/src/completion/complete_keyword.rs
@@ -88,7 +88,7 @@ fn is_in_loop_body(leaf: &SyntaxToken) -> bool {
88 .visit::<ast::LoopExpr, _>(|it| it.loop_body()) 88 .visit::<ast::LoopExpr, _>(|it| it.loop_body())
89 .accept(&node); 89 .accept(&node);
90 if let Some(Some(body)) = loop_body { 90 if let Some(Some(body)) = loop_body {
91 if leaf.range().is_subrange(&body.syntax().range()) { 91 if leaf.text_range().is_subrange(&body.syntax().text_range()) {
92 return true; 92 return true;
93 } 93 }
94 } 94 }
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index 29586cd1f..5fd41eeb3 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -26,7 +26,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
26 if Some(module) == ctx.module { 26 if Some(module) == ctx.module {
27 if let Some(import) = res.import { 27 if let Some(import) = res.import {
28 if let Either::A(use_tree) = module.import_source(ctx.db, import) { 28 if let Either::A(use_tree) = module.import_source(ctx.db, import) {
29 if use_tree.syntax().range().contains_inclusive(ctx.offset) { 29 if use_tree.syntax().text_range().contains_inclusive(ctx.offset) {
30 // for `use self::foo<|>`, don't suggest `foo` as a completion 30 // for `use self::foo<|>`, don't suggest `foo` as a completion
31 tested_by!(dont_complete_current_use); 31 tested_by!(dont_complete_current_use);
32 continue; 32 continue;
diff --git a/crates/ra_ide_api/src/completion/complete_postfix.rs b/crates/ra_ide_api/src/completion/complete_postfix.rs
index c75b1c159..6d834f6ce 100644
--- a/crates/ra_ide_api/src/completion/complete_postfix.rs
+++ b/crates/ra_ide_api/src/completion/complete_postfix.rs
@@ -12,7 +12,7 @@ use ra_text_edit::TextEditBuilder;
12fn postfix_snippet(ctx: &CompletionContext, label: &str, detail: &str, snippet: &str) -> Builder { 12fn postfix_snippet(ctx: &CompletionContext, label: &str, detail: &str, snippet: &str) -> Builder {
13 let edit = { 13 let edit = {
14 let receiver_range = 14 let receiver_range =
15 ctx.dot_receiver.as_ref().expect("no receiver available").syntax().range(); 15 ctx.dot_receiver.as_ref().expect("no receiver available").syntax().text_range();
16 let delete_range = TextRange::from_to(receiver_range.start(), ctx.source_range().end()); 16 let delete_range = TextRange::from_to(receiver_range.start(), ctx.source_range().end());
17 let mut builder = TextEditBuilder::default(); 17 let mut builder = TextEditBuilder::default();
18 builder.replace(delete_range, snippet.to_string()); 18 builder.replace(delete_range, snippet.to_string());
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs
index b803271ab..2f78d5409 100644
--- a/crates/ra_ide_api/src/completion/completion_context.rs
+++ b/crates/ra_ide_api/src/completion/completion_context.rs
@@ -78,7 +78,7 @@ impl<'a> CompletionContext<'a> {
78 pub(crate) fn source_range(&self) -> TextRange { 78 pub(crate) fn source_range(&self) -> TextRange {
79 match self.token.kind() { 79 match self.token.kind() {
80 // workaroud when completion is triggered by trigger characters. 80 // workaroud when completion is triggered by trigger characters.
81 IDENT => self.token.range(), 81 IDENT => self.token.text_range(),
82 _ => TextRange::offset_len(self.offset, 0.into()), 82 _ => TextRange::offset_len(self.offset, 0.into()),
83 } 83 }
84 } 84 }
@@ -123,13 +123,17 @@ impl<'a> CompletionContext<'a> {
123 } 123 }
124 124
125 fn classify_name_ref(&mut self, original_file: SourceFile, name_ref: ast::NameRef) { 125 fn classify_name_ref(&mut self, original_file: SourceFile, name_ref: ast::NameRef) {
126 let name_range = name_ref.syntax().range(); 126 let name_range = name_ref.syntax().text_range();
127 if name_ref.syntax().parent().and_then(ast::NamedField::cast).is_some() { 127 if name_ref.syntax().parent().and_then(ast::NamedField::cast).is_some() {
128 self.struct_lit_syntax = find_node_at_offset(original_file.syntax(), self.offset); 128 self.struct_lit_syntax = find_node_at_offset(original_file.syntax(), self.offset);
129 } 129 }
130 130
131 let top_node = 131 let top_node = name_ref
132 name_ref.syntax().ancestors().take_while(|it| it.range() == name_range).last().unwrap(); 132 .syntax()
133 .ancestors()
134 .take_while(|it| it.text_range() == name_range)
135 .last()
136 .unwrap();
133 137
134 match top_node.parent().map(|it| it.kind()) { 138 match top_node.parent().map(|it| it.kind()) {
135 Some(SOURCE_FILE) | Some(ITEM_LIST) => { 139 Some(SOURCE_FILE) | Some(ITEM_LIST) => {
@@ -180,23 +184,27 @@ impl<'a> CompletionContext<'a> {
180 .ancestors() 184 .ancestors()
181 .find_map(|node| { 185 .find_map(|node| {
182 if let Some(stmt) = ast::ExprStmt::cast(node.clone()) { 186 if let Some(stmt) = ast::ExprStmt::cast(node.clone()) {
183 return Some(stmt.syntax().range() == name_ref.syntax().range()); 187 return Some(
188 stmt.syntax().text_range() == name_ref.syntax().text_range(),
189 );
184 } 190 }
185 if let Some(block) = ast::Block::cast(node) { 191 if let Some(block) = ast::Block::cast(node) {
186 return Some( 192 return Some(
187 block.expr().map(|e| e.syntax().range()) 193 block.expr().map(|e| e.syntax().text_range())
188 == Some(name_ref.syntax().range()), 194 == Some(name_ref.syntax().text_range()),
189 ); 195 );
190 } 196 }
191 None 197 None
192 }) 198 })
193 .unwrap_or(false); 199 .unwrap_or(false);
194 200
195 if let Some(off) = name_ref.syntax().range().start().checked_sub(2.into()) { 201 if let Some(off) = name_ref.syntax().text_range().start().checked_sub(2.into()) {
196 if let Some(if_expr) = 202 if let Some(if_expr) =
197 find_node_at_offset::<ast::IfExpr>(original_file.syntax(), off) 203 find_node_at_offset::<ast::IfExpr>(original_file.syntax(), off)
198 { 204 {
199 if if_expr.syntax().range().end() < name_ref.syntax().range().start() { 205 if if_expr.syntax().text_range().end()
206 < name_ref.syntax().text_range().start()
207 {
200 self.after_if = true; 208 self.after_if = true;
201 } 209 }
202 } 210 }
@@ -208,14 +216,14 @@ impl<'a> CompletionContext<'a> {
208 // ident, so it should have the same range in the non-modified file 216 // ident, so it should have the same range in the non-modified file
209 self.dot_receiver = field_expr 217 self.dot_receiver = field_expr
210 .expr() 218 .expr()
211 .map(|e| e.syntax().range()) 219 .map(|e| e.syntax().text_range())
212 .and_then(|r| find_node_with_range(original_file.syntax(), r)); 220 .and_then(|r| find_node_with_range(original_file.syntax(), r));
213 } 221 }
214 if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent) { 222 if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent) {
215 // As above 223 // As above
216 self.dot_receiver = method_call_expr 224 self.dot_receiver = method_call_expr
217 .expr() 225 .expr()
218 .map(|e| e.syntax().range()) 226 .map(|e| e.syntax().text_range())
219 .and_then(|r| find_node_with_range(original_file.syntax(), r)); 227 .and_then(|r| find_node_with_range(original_file.syntax(), r));
220 self.is_call = true; 228 self.is_call = true;
221 } 229 }
@@ -229,6 +237,6 @@ fn find_node_with_range<N: AstNode>(syntax: &SyntaxNode, range: TextRange) -> Op
229fn is_node<N: AstNode>(node: &SyntaxNode) -> bool { 237fn is_node<N: AstNode>(node: &SyntaxNode) -> bool {
230 match node.ancestors().filter_map(N::cast).next() { 238 match node.ancestors().filter_map(N::cast).next() {
231 None => false, 239 None => false,
232 Some(n) => n.syntax().range() == node.range(), 240 Some(n) => n.syntax().text_range() == node.text_range(),
233 } 241 }
234} 242}
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs
index affbad6cd..028dc3d4f 100644
--- a/crates/ra_ide_api/src/diagnostics.rs
+++ b/crates/ra_ide_api/src/diagnostics.rs
@@ -96,7 +96,7 @@ fn check_unnecessary_braces_in_use_statement(
96) -> Option<()> { 96) -> Option<()> {
97 let use_tree_list = ast::UseTreeList::cast(node.clone())?; 97 let use_tree_list = ast::UseTreeList::cast(node.clone())?;
98 if let Some((single_use_tree,)) = use_tree_list.use_trees().collect_tuple() { 98 if let Some((single_use_tree,)) = use_tree_list.use_trees().collect_tuple() {
99 let range = use_tree_list.syntax().range(); 99 let range = use_tree_list.syntax().text_range();
100 let edit = 100 let edit =
101 text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(&single_use_tree) 101 text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(&single_use_tree)
102 .unwrap_or_else(|| { 102 .unwrap_or_else(|| {
@@ -126,8 +126,8 @@ fn text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(
126) -> Option<TextEdit> { 126) -> Option<TextEdit> {
127 let use_tree_list_node = single_use_tree.syntax().parent()?; 127 let use_tree_list_node = single_use_tree.syntax().parent()?;
128 if single_use_tree.path()?.segment()?.syntax().first_child_or_token()?.kind() == T![self] { 128 if single_use_tree.path()?.segment()?.syntax().first_child_or_token()?.kind() == T![self] {
129 let start = use_tree_list_node.prev_sibling_or_token()?.range().start(); 129 let start = use_tree_list_node.prev_sibling_or_token()?.text_range().start();
130 let end = use_tree_list_node.range().end(); 130 let end = use_tree_list_node.text_range().end();
131 let range = TextRange::from_to(start, end); 131 let range = TextRange::from_to(start, end);
132 let mut edit_builder = TextEditBuilder::default(); 132 let mut edit_builder = TextEditBuilder::default();
133 edit_builder.delete(range); 133 edit_builder.delete(range);
@@ -149,12 +149,12 @@ fn check_struct_shorthand_initialization(
149 let field_expr = expr.syntax().text().to_string(); 149 let field_expr = expr.syntax().text().to_string();
150 if field_name == field_expr { 150 if field_name == field_expr {
151 let mut edit_builder = TextEditBuilder::default(); 151 let mut edit_builder = TextEditBuilder::default();
152 edit_builder.delete(named_field.syntax().range()); 152 edit_builder.delete(named_field.syntax().text_range());
153 edit_builder.insert(named_field.syntax().range().start(), field_name); 153 edit_builder.insert(named_field.syntax().text_range().start(), field_name);
154 let edit = edit_builder.finish(); 154 let edit = edit_builder.finish();
155 155
156 acc.push(Diagnostic { 156 acc.push(Diagnostic {
157 range: named_field.syntax().range(), 157 range: named_field.syntax().text_range(),
158 message: "Shorthand struct initialization".to_string(), 158 message: "Shorthand struct initialization".to_string(),
159 severity: Severity::WeakWarning, 159 severity: Severity::WeakWarning,
160 fix: Some(SourceChange::source_file_edit( 160 fix: Some(SourceChange::source_file_edit(
diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs
index 8aff5f2cd..84fabdb9e 100644
--- a/crates/ra_ide_api/src/display/navigation_target.rs
+++ b/crates/ra_ide_api/src/display/navigation_target.rs
@@ -233,7 +233,7 @@ impl NavigationTarget {
233 233
234 pub(crate) fn from_macro_def(db: &RootDatabase, macro_call: hir::MacroDef) -> NavigationTarget { 234 pub(crate) fn from_macro_def(db: &RootDatabase, macro_call: hir::MacroDef) -> NavigationTarget {
235 let src = macro_call.source(db); 235 let src = macro_call.source(db);
236 log::debug!("nav target {}", src.ast.syntax().debug_dump()); 236 log::debug!("nav target {:#?}", src.ast.syntax());
237 NavigationTarget::from_named( 237 NavigationTarget::from_named(
238 src.file_id.original_file(db), 238 src.file_id.original_file(db),
239 &src.ast, 239 &src.ast,
@@ -275,7 +275,7 @@ impl NavigationTarget {
275 ) -> NavigationTarget { 275 ) -> NavigationTarget {
276 //FIXME: use `_` instead of empty string 276 //FIXME: use `_` instead of empty string
277 let name = node.name().map(|it| it.text().clone()).unwrap_or_default(); 277 let name = node.name().map(|it| it.text().clone()).unwrap_or_default();
278 let focus_range = node.name().map(|it| it.syntax().range()); 278 let focus_range = node.name().map(|it| it.syntax().text_range());
279 NavigationTarget::from_syntax(file_id, name, focus_range, node.syntax(), docs, description) 279 NavigationTarget::from_syntax(file_id, name, focus_range, node.syntax(), docs, description)
280 } 280 }
281 281
@@ -291,7 +291,7 @@ impl NavigationTarget {
291 file_id, 291 file_id,
292 name, 292 name,
293 kind: node.kind(), 293 kind: node.kind(),
294 full_range: node.range(), 294 full_range: node.text_range(),
295 focus_range, 295 focus_range,
296 // ptr: Some(LocalSyntaxPtr::new(node)), 296 // ptr: Some(LocalSyntaxPtr::new(node)),
297 container_name: None, 297 container_name: None,
diff --git a/crates/ra_ide_api/src/display/structure.rs b/crates/ra_ide_api/src/display/structure.rs
index 0b1a8b6e6..2ba10b2ef 100644
--- a/crates/ra_ide_api/src/display/structure.rs
+++ b/crates/ra_ide_api/src/display/structure.rs
@@ -73,8 +73,8 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
73 Some(StructureNode { 73 Some(StructureNode {
74 parent: None, 74 parent: None,
75 label: name.text().to_string(), 75 label: name.text().to_string(),
76 navigation_range: name.syntax().range(), 76 navigation_range: name.syntax().text_range(),
77 node_range: node.syntax().range(), 77 node_range: node.syntax().text_range(),
78 kind: node.syntax().kind(), 78 kind: node.syntax().kind(),
79 detail, 79 detail,
80 deprecated: node.attrs().filter_map(|x| x.as_named()).any(|x| x == "deprecated"), 80 deprecated: node.attrs().filter_map(|x| x.as_named()).any(|x| x == "deprecated"),
@@ -140,8 +140,8 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
140 let node = StructureNode { 140 let node = StructureNode {
141 parent: None, 141 parent: None,
142 label, 142 label,
143 navigation_range: target_type.syntax().range(), 143 navigation_range: target_type.syntax().text_range(),
144 node_range: im.syntax().range(), 144 node_range: im.syntax().text_range(),
145 kind: im.syntax().kind(), 145 kind: im.syntax().kind(),
146 detail: None, 146 detail: None,
147 deprecated: false, 147 deprecated: false,
diff --git a/crates/ra_ide_api/src/extend_selection.rs b/crates/ra_ide_api/src/extend_selection.rs
index 292f61f4a..140820df6 100644
--- a/crates/ra_ide_api/src/extend_selection.rs
+++ b/crates/ra_ide_api/src/extend_selection.rs
@@ -42,19 +42,20 @@ fn try_extend_selection(root: &SyntaxNode, range: TextRange) -> Option<TextRange
42 TokenAtOffset::None => return None, 42 TokenAtOffset::None => return None,
43 TokenAtOffset::Single(l) => { 43 TokenAtOffset::Single(l) => {
44 if string_kinds.contains(&l.kind()) { 44 if string_kinds.contains(&l.kind()) {
45 extend_single_word_in_comment_or_string(&l, offset).unwrap_or_else(|| l.range()) 45 extend_single_word_in_comment_or_string(&l, offset)
46 .unwrap_or_else(|| l.text_range())
46 } else { 47 } else {
47 l.range() 48 l.text_range()
48 } 49 }
49 } 50 }
50 TokenAtOffset::Between(l, r) => pick_best(l, r).range(), 51 TokenAtOffset::Between(l, r) => pick_best(l, r).text_range(),
51 }; 52 };
52 return Some(leaf_range); 53 return Some(leaf_range);
53 }; 54 };
54 let node = match find_covering_element(root, range) { 55 let node = match find_covering_element(root, range) {
55 SyntaxElement::Token(token) => { 56 SyntaxElement::Token(token) => {
56 if token.range() != range { 57 if token.text_range() != range {
57 return Some(token.range()); 58 return Some(token.text_range());
58 } 59 }
59 if let Some(comment) = ast::Comment::cast(token.clone()) { 60 if let Some(comment) = ast::Comment::cast(token.clone()) {
60 if let Some(range) = extend_comments(comment) { 61 if let Some(range) = extend_comments(comment) {
@@ -65,12 +66,12 @@ fn try_extend_selection(root: &SyntaxNode, range: TextRange) -> Option<TextRange
65 } 66 }
66 SyntaxElement::Node(node) => node, 67 SyntaxElement::Node(node) => node,
67 }; 68 };
68 if node.range() != range { 69 if node.text_range() != range {
69 return Some(node.range()); 70 return Some(node.text_range());
70 } 71 }
71 72
72 // Using shallowest node with same range allows us to traverse siblings. 73 // Using shallowest node with same range allows us to traverse siblings.
73 let node = node.ancestors().take_while(|n| n.range() == node.range()).last().unwrap(); 74 let node = node.ancestors().take_while(|n| n.text_range() == node.text_range()).last().unwrap();
74 75
75 if node.parent().map(|n| list_kinds.contains(&n.kind())) == Some(true) { 76 if node.parent().map(|n| list_kinds.contains(&n.kind())) == Some(true) {
76 if let Some(range) = extend_list_item(&node) { 77 if let Some(range) = extend_list_item(&node) {
@@ -78,7 +79,7 @@ fn try_extend_selection(root: &SyntaxNode, range: TextRange) -> Option<TextRange
78 } 79 }
79 } 80 }
80 81
81 node.parent().map(|it| it.range()) 82 node.parent().map(|it| it.text_range())
82} 83}
83 84
84fn extend_single_word_in_comment_or_string( 85fn extend_single_word_in_comment_or_string(
@@ -86,7 +87,7 @@ fn extend_single_word_in_comment_or_string(
86 offset: TextUnit, 87 offset: TextUnit,
87) -> Option<TextRange> { 88) -> Option<TextRange> {
88 let text: &str = leaf.text(); 89 let text: &str = leaf.text();
89 let cursor_position: u32 = (offset - leaf.range().start()).into(); 90 let cursor_position: u32 = (offset - leaf.text_range().start()).into();
90 91
91 let (before, after) = text.split_at(cursor_position as usize); 92 let (before, after) = text.split_at(cursor_position as usize);
92 93
@@ -104,31 +105,31 @@ fn extend_single_word_in_comment_or_string(
104 if range.is_empty() { 105 if range.is_empty() {
105 None 106 None
106 } else { 107 } else {
107 Some(range + leaf.range().start()) 108 Some(range + leaf.text_range().start())
108 } 109 }
109} 110}
110 111
111fn extend_ws(root: &SyntaxNode, ws: SyntaxToken, offset: TextUnit) -> TextRange { 112fn extend_ws(root: &SyntaxNode, ws: SyntaxToken, offset: TextUnit) -> TextRange {
112 let ws_text = ws.text(); 113 let ws_text = ws.text();
113 let suffix = TextRange::from_to(offset, ws.range().end()) - ws.range().start(); 114 let suffix = TextRange::from_to(offset, ws.text_range().end()) - ws.text_range().start();
114 let prefix = TextRange::from_to(ws.range().start(), offset) - ws.range().start(); 115 let prefix = TextRange::from_to(ws.text_range().start(), offset) - ws.text_range().start();
115 let ws_suffix = &ws_text.as_str()[suffix]; 116 let ws_suffix = &ws_text.as_str()[suffix];
116 let ws_prefix = &ws_text.as_str()[prefix]; 117 let ws_prefix = &ws_text.as_str()[prefix];
117 if ws_text.contains('\n') && !ws_suffix.contains('\n') { 118 if ws_text.contains('\n') && !ws_suffix.contains('\n') {
118 if let Some(node) = ws.next_sibling_or_token() { 119 if let Some(node) = ws.next_sibling_or_token() {
119 let start = match ws_prefix.rfind('\n') { 120 let start = match ws_prefix.rfind('\n') {
120 Some(idx) => ws.range().start() + TextUnit::from((idx + 1) as u32), 121 Some(idx) => ws.text_range().start() + TextUnit::from((idx + 1) as u32),
121 None => node.range().start(), 122 None => node.text_range().start(),
122 }; 123 };
123 let end = if root.text().char_at(node.range().end()) == Some('\n') { 124 let end = if root.text().char_at(node.text_range().end()) == Some('\n') {
124 node.range().end() + TextUnit::of_char('\n') 125 node.text_range().end() + TextUnit::of_char('\n')
125 } else { 126 } else {
126 node.range().end() 127 node.text_range().end()
127 }; 128 };
128 return TextRange::from_to(start, end); 129 return TextRange::from_to(start, end);
129 } 130 }
130 } 131 }
131 ws.range() 132 ws.text_range()
132} 133}
133 134
134fn pick_best<'a>(l: SyntaxToken, r: SyntaxToken) -> SyntaxToken { 135fn pick_best<'a>(l: SyntaxToken, r: SyntaxToken) -> SyntaxToken {
@@ -161,7 +162,7 @@ fn extend_list_item(node: &SyntaxNode) -> Option<TextRange> {
161 } 162 }
162 163
163 if let Some(comma_node) = nearby_comma(node, Direction::Prev) { 164 if let Some(comma_node) = nearby_comma(node, Direction::Prev) {
164 return Some(TextRange::from_to(comma_node.range().start(), node.range().end())); 165 return Some(TextRange::from_to(comma_node.text_range().start(), node.text_range().end()));
165 } 166 }
166 if let Some(comma_node) = nearby_comma(node, Direction::Next) { 167 if let Some(comma_node) = nearby_comma(node, Direction::Next) {
167 // Include any following whitespace when comma if after list item. 168 // Include any following whitespace when comma if after list item.
@@ -171,7 +172,7 @@ fn extend_list_item(node: &SyntaxNode) -> Option<TextRange> {
171 .filter(|node| is_single_line_ws(node)) 172 .filter(|node| is_single_line_ws(node))
172 .unwrap_or(comma_node); 173 .unwrap_or(comma_node);
173 174
174 return Some(TextRange::from_to(node.range().start(), final_node.range().end())); 175 return Some(TextRange::from_to(node.text_range().start(), final_node.text_range().end()));
175 } 176 }
176 177
177 None 178 None
@@ -181,7 +182,10 @@ fn extend_comments(comment: ast::Comment) -> Option<TextRange> {
181 let prev = adj_comments(&comment, Direction::Prev); 182 let prev = adj_comments(&comment, Direction::Prev);
182 let next = adj_comments(&comment, Direction::Next); 183 let next = adj_comments(&comment, Direction::Next);
183 if prev != next { 184 if prev != next {
184 Some(TextRange::from_to(prev.syntax().range().start(), next.syntax().range().end())) 185 Some(TextRange::from_to(
186 prev.syntax().text_range().start(),
187 next.syntax().text_range().end(),
188 ))
185 } else { 189 } else {
186 None 190 None
187 } 191 }
diff --git a/crates/ra_ide_api/src/folding_ranges.rs b/crates/ra_ide_api/src/folding_ranges.rs
index c2b981aed..9699000db 100644
--- a/crates/ra_ide_api/src/folding_ranges.rs
+++ b/crates/ra_ide_api/src/folding_ranges.rs
@@ -35,7 +35,7 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
35 SyntaxElement::Token(token) => token.text().contains('\n'), 35 SyntaxElement::Token(token) => token.text().contains('\n'),
36 }; 36 };
37 if is_multiline { 37 if is_multiline {
38 res.push(Fold { range: element.range(), kind }); 38 res.push(Fold { range: element.text_range(), kind });
39 continue; 39 continue;
40 } 40 }
41 } 41 }
@@ -132,7 +132,7 @@ fn contiguous_range_for_group_unless(
132 } 132 }
133 133
134 if first != &last { 134 if first != &last {
135 Some(TextRange::from_to(first.range().start(), last.range().end())) 135 Some(TextRange::from_to(first.text_range().start(), last.text_range().end()))
136 } else { 136 } else {
137 // The group consists of only one element, therefore it cannot be folded 137 // The group consists of only one element, therefore it cannot be folded
138 None 138 None
@@ -178,7 +178,10 @@ fn contiguous_range_for_comment(
178 } 178 }
179 179
180 if first != last { 180 if first != last {
181 Some(TextRange::from_to(first.syntax().range().start(), last.syntax().range().end())) 181 Some(TextRange::from_to(
182 first.syntax().text_range().start(),
183 last.syntax().text_range().end(),
184 ))
182 } else { 185 } else {
183 // The group consists of only one element, therefore it cannot be folded 186 // The group consists of only one element, therefore it cannot be folded
184 None 187 None
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index 82b5e3b5e..ddd55a9c1 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -23,11 +23,11 @@ pub(crate) fn goto_definition(
23 let syntax = parse.tree().syntax().clone(); 23 let syntax = parse.tree().syntax().clone();
24 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&syntax, position.offset) { 24 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&syntax, position.offset) {
25 let navs = reference_definition(db, position.file_id, &name_ref).to_vec(); 25 let navs = reference_definition(db, position.file_id, &name_ref).to_vec();
26 return Some(RangeInfo::new(name_ref.syntax().range(), navs.to_vec())); 26 return Some(RangeInfo::new(name_ref.syntax().text_range(), navs.to_vec()));
27 } 27 }
28 if let Some(name) = find_node_at_offset::<ast::Name>(&syntax, position.offset) { 28 if let Some(name) = find_node_at_offset::<ast::Name>(&syntax, position.offset) {
29 let navs = name_definition(db, position.file_id, &name)?; 29 let navs = name_definition(db, position.file_id, &name)?;
30 return Some(RangeInfo::new(name.syntax().range(), navs)); 30 return Some(RangeInfo::new(name.syntax().text_range(), navs));
31 } 31 }
32 None 32 None
33} 33}
diff --git a/crates/ra_ide_api/src/goto_type_definition.rs b/crates/ra_ide_api/src/goto_type_definition.rs
index fc4b6e1af..007259d9e 100644
--- a/crates/ra_ide_api/src/goto_type_definition.rs
+++ b/crates/ra_ide_api/src/goto_type_definition.rs
@@ -32,7 +32,7 @@ pub(crate) fn goto_type_definition(
32 let adt_def = analyzer.autoderef(db, ty).find_map(|ty| ty.as_adt().map(|adt| adt.0))?; 32 let adt_def = analyzer.autoderef(db, ty).find_map(|ty| ty.as_adt().map(|adt| adt.0))?;
33 33
34 let nav = NavigationTarget::from_adt_def(db, adt_def); 34 let nav = NavigationTarget::from_adt_def(db, adt_def);
35 Some(RangeInfo::new(node.range(), vec![nav])) 35 Some(RangeInfo::new(node.text_range(), vec![nav]))
36} 36}
37 37
38#[cfg(test)] 38#[cfg(test)]
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index e503bf6a9..2a5ac7821 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -172,7 +172,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
172 } 172 }
173 173
174 if !res.is_empty() { 174 if !res.is_empty() {
175 range = Some(name_ref.syntax().range()) 175 range = Some(name_ref.syntax().text_range())
176 } 176 }
177 } else if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), position.offset) { 177 } else if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), position.offset) {
178 if let Some(parent) = name.syntax().parent() { 178 if let Some(parent) = name.syntax().parent() {
@@ -210,7 +210,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
210 } 210 }
211 211
212 if !res.is_empty() && range.is_none() { 212 if !res.is_empty() && range.is_none() {
213 range = Some(name.syntax().range()); 213 range = Some(name.syntax().text_range());
214 } 214 }
215 } 215 }
216 216
@@ -218,9 +218,9 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
218 let node = ancestors_at_offset(file.syntax(), position.offset).find(|n| { 218 let node = ancestors_at_offset(file.syntax(), position.offset).find(|n| {
219 ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some() 219 ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some()
220 })?; 220 })?;
221 let frange = FileRange { file_id: position.file_id, range: node.range() }; 221 let frange = FileRange { file_id: position.file_id, range: node.text_range() };
222 res.extend(type_of(db, frange).map(rust_code_markup)); 222 res.extend(type_of(db, frange).map(rust_code_markup));
223 range = Some(node.range()); 223 range = Some(node.text_range());
224 } 224 }
225 225
226 let range = range?; 226 let range = range?;
@@ -246,7 +246,7 @@ pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option<String> {
246 // if we picked identifier, expand to pattern/expression 246 // if we picked identifier, expand to pattern/expression
247 let node = leaf_node 247 let node = leaf_node
248 .ancestors() 248 .ancestors()
249 .take_while(|it| it.range() == leaf_node.range()) 249 .take_while(|it| it.text_range() == leaf_node.text_range())
250 .find(|it| ast::Expr::cast(it.clone()).is_some() || ast::Pat::cast(it.clone()).is_some())?; 250 .find(|it| ast::Expr::cast(it.clone()).is_some() || ast::Pat::cast(it.clone()).is_some())?;
251 let analyzer = hir::SourceAnalyzer::new(db, frange.file_id, &node, None); 251 let analyzer = hir::SourceAnalyzer::new(db, frange.file_id, &node, None);
252 let ty = if let Some(ty) = ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e)) 252 let ty = if let Some(ty) = ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e))
diff --git a/crates/ra_ide_api/src/impls.rs b/crates/ra_ide_api/src/impls.rs
index 15999d433..f5b6ffd61 100644
--- a/crates/ra_ide_api/src/impls.rs
+++ b/crates/ra_ide_api/src/impls.rs
@@ -15,12 +15,12 @@ pub(crate) fn goto_implementation(
15 15
16 if let Some(nominal_def) = find_node_at_offset::<ast::NominalDef>(&syntax, position.offset) { 16 if let Some(nominal_def) = find_node_at_offset::<ast::NominalDef>(&syntax, position.offset) {
17 return Some(RangeInfo::new( 17 return Some(RangeInfo::new(
18 nominal_def.syntax().range(), 18 nominal_def.syntax().text_range(),
19 impls_for_def(db, &nominal_def, module)?, 19 impls_for_def(db, &nominal_def, module)?,
20 )); 20 ));
21 } else if let Some(trait_def) = find_node_at_offset::<ast::TraitDef>(&syntax, position.offset) { 21 } else if let Some(trait_def) = find_node_at_offset::<ast::TraitDef>(&syntax, position.offset) {
22 return Some(RangeInfo::new( 22 return Some(RangeInfo::new(
23 trait_def.syntax().range(), 23 trait_def.syntax().text_range(),
24 impls_for_trait(db, &trait_def, module)?, 24 impls_for_trait(db, &trait_def, module)?,
25 )); 25 ));
26 } 26 }
diff --git a/crates/ra_ide_api/src/join_lines.rs b/crates/ra_ide_api/src/join_lines.rs
index 9b81ad9e4..fa998ebe1 100644
--- a/crates/ra_ide_api/src/join_lines.rs
+++ b/crates/ra_ide_api/src/join_lines.rs
@@ -28,14 +28,14 @@ pub fn join_lines(file: &SourceFile, range: TextRange) -> TextEdit {
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()) {
31 let range = match range.intersection(&token.range()) { 31 let range = match range.intersection(&token.text_range()) {
32 Some(range) => range, 32 Some(range) => range,
33 None => continue, 33 None => continue,
34 } - token.range().start(); 34 } - token.text_range().start();
35 let text = token.text(); 35 let text = token.text();
36 for (pos, _) in text[range].bytes().enumerate().filter(|&(_, b)| b == b'\n') { 36 for (pos, _) in text[range].bytes().enumerate().filter(|&(_, b)| b == b'\n') {
37 let pos: TextUnit = (pos as u32).into(); 37 let pos: TextUnit = (pos as u32).into();
38 let off = token.range().start() + range.start() + pos; 38 let off = token.text_range().start() + range.start() + pos;
39 if !edit.invalidates_offset(off) { 39 if !edit.invalidates_offset(off) {
40 remove_newline(&mut edit, &token, off); 40 remove_newline(&mut edit, &token, off);
41 } 41 }
@@ -49,7 +49,7 @@ fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextU
49 if token.kind() != WHITESPACE || token.text().bytes().filter(|&b| b == b'\n').count() != 1 { 49 if token.kind() != WHITESPACE || token.text().bytes().filter(|&b| b == b'\n').count() != 1 {
50 // The node is either the first or the last in the file 50 // The node is either the first or the last in the file
51 let suff = &token.text()[TextRange::from_to( 51 let suff = &token.text()[TextRange::from_to(
52 offset - token.range().start() + TextUnit::of_char('\n'), 52 offset - token.text_range().start() + TextUnit::of_char('\n'),
53 TextUnit::of_str(token.text()), 53 TextUnit::of_str(token.text()),
54 )]; 54 )];
55 let spaces = suff.bytes().take_while(|&b| b == b' ').count(); 55 let spaces = suff.bytes().take_while(|&b| b == b' ').count();
@@ -86,7 +86,7 @@ fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextU
86 let next = token.next_sibling_or_token().unwrap(); 86 let next = token.next_sibling_or_token().unwrap();
87 if is_trailing_comma(prev.kind(), next.kind()) { 87 if is_trailing_comma(prev.kind(), next.kind()) {
88 // Removes: trailing comma, newline (incl. surrounding whitespace) 88 // Removes: trailing comma, newline (incl. surrounding whitespace)
89 edit.delete(TextRange::from_to(prev.range().start(), token.range().end())); 89 edit.delete(TextRange::from_to(prev.text_range().start(), token.text_range().end()));
90 } else if prev.kind() == T![,] && next.kind() == T!['}'] { 90 } else if prev.kind() == T![,] && next.kind() == T!['}'] {
91 // Removes: comma, newline (incl. surrounding whitespace) 91 // Removes: comma, newline (incl. surrounding whitespace)
92 let space = if let Some(left) = prev.prev_sibling_or_token() { 92 let space = if let Some(left) = prev.prev_sibling_or_token() {
@@ -95,7 +95,7 @@ fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextU
95 " " 95 " "
96 }; 96 };
97 edit.replace( 97 edit.replace(
98 TextRange::from_to(prev.range().start(), token.range().end()), 98 TextRange::from_to(prev.text_range().start(), token.text_range().end()),
99 space.to_string(), 99 space.to_string(),
100 ); 100 );
101 } else if let (Some(_), Some(next)) = ( 101 } else if let (Some(_), Some(next)) = (
@@ -104,12 +104,12 @@ fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextU
104 ) { 104 ) {
105 // Removes: newline (incl. surrounding whitespace), start of the next comment 105 // Removes: newline (incl. surrounding whitespace), start of the next comment
106 edit.delete(TextRange::from_to( 106 edit.delete(TextRange::from_to(
107 token.range().start(), 107 token.text_range().start(),
108 next.syntax().range().start() + TextUnit::of_str(next.prefix()), 108 next.syntax().text_range().start() + TextUnit::of_str(next.prefix()),
109 )); 109 ));
110 } else { 110 } else {
111 // Remove newline but add a computed amount of whitespace characters 111 // Remove newline but add a computed amount of whitespace characters
112 edit.replace(token.range(), compute_ws(prev.kind(), next.kind()).to_string()); 112 edit.replace(token.text_range(), compute_ws(prev.kind(), next.kind()).to_string());
113 } 113 }
114} 114}
115 115
@@ -125,7 +125,7 @@ fn join_single_expr_block(edit: &mut TextEditBuilder, token: &SyntaxToken) -> Op
125 let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?; 125 let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?;
126 let expr = extract_trivial_expression(&block)?; 126 let expr = extract_trivial_expression(&block)?;
127 127
128 let block_range = block_expr.syntax().range(); 128 let block_range = block_expr.syntax().text_range();
129 let mut buf = expr.syntax().text().to_string(); 129 let mut buf = expr.syntax().text().to_string();
130 130
131 // Match block needs to have a comma after the block 131 // Match block needs to have a comma after the block
@@ -143,7 +143,7 @@ fn join_single_expr_block(edit: &mut TextEditBuilder, token: &SyntaxToken) -> Op
143fn join_single_use_tree(edit: &mut TextEditBuilder, token: &SyntaxToken) -> Option<()> { 143fn join_single_use_tree(edit: &mut TextEditBuilder, token: &SyntaxToken) -> Option<()> {
144 let use_tree_list = ast::UseTreeList::cast(token.parent())?; 144 let use_tree_list = ast::UseTreeList::cast(token.parent())?;
145 let (tree,) = use_tree_list.use_trees().collect_tuple()?; 145 let (tree,) = use_tree_list.use_trees().collect_tuple()?;
146 edit.replace(use_tree_list.syntax().range(), tree.syntax().text().to_string()); 146 edit.replace(use_tree_list.syntax().text_range(), tree.syntax().text().to_string());
147 Some(()) 147 Some(())
148} 148}
149 149
diff --git a/crates/ra_ide_api/src/matching_brace.rs b/crates/ra_ide_api/src/matching_brace.rs
index 102327fd7..1e2fac848 100644
--- a/crates/ra_ide_api/src/matching_brace.rs
+++ b/crates/ra_ide_api/src/matching_brace.rs
@@ -12,7 +12,7 @@ pub fn matching_brace(file: &SourceFile, offset: TextUnit) -> Option<TextUnit> {
12 let parent = brace_node.parent(); 12 let parent = brace_node.parent();
13 let matching_kind = BRACES[brace_idx ^ 1]; 13 let matching_kind = BRACES[brace_idx ^ 1];
14 let matching_node = parent.children_with_tokens().find(|node| node.kind() == matching_kind)?; 14 let matching_node = parent.children_with_tokens().find(|node| node.kind() == matching_kind)?;
15 Some(matching_node.range().start()) 15 Some(matching_node.text_range().start())
16} 16}
17 17
18#[cfg(test)] 18#[cfg(test)]
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs
index 1c4cd49dc..5c74d3e36 100644
--- a/crates/ra_ide_api/src/references.rs
+++ b/crates/ra_ide_api/src/references.rs
@@ -166,7 +166,7 @@ fn rename_mod(
166 file_id: position.file_id, 166 file_id: position.file_id,
167 edit: { 167 edit: {
168 let mut builder = ra_text_edit::TextEditBuilder::default(); 168 let mut builder = ra_text_edit::TextEditBuilder::default();
169 builder.replace(ast_name.syntax().range(), new_name.into()); 169 builder.replace(ast_name.syntax().text_range(), new_name.into());
170 builder.finish() 170 builder.finish()
171 }, 171 },
172 }; 172 };
diff --git a/crates/ra_ide_api/src/runnables.rs b/crates/ra_ide_api/src/runnables.rs
index 200958434..07412a9ef 100644
--- a/crates/ra_ide_api/src/runnables.rs
+++ b/crates/ra_ide_api/src/runnables.rs
@@ -47,7 +47,7 @@ fn runnable_fn(fn_def: ast::FnDef) -> Option<Runnable> {
47 } else { 47 } else {
48 return None; 48 return None;
49 }; 49 };
50 Some(Runnable { range: fn_def.syntax().range(), kind }) 50 Some(Runnable { range: fn_def.syntax().text_range(), kind })
51} 51}
52 52
53fn runnable_mod(db: &RootDatabase, file_id: FileId, module: ast::Module) -> Option<Runnable> { 53fn runnable_mod(db: &RootDatabase, file_id: FileId, module: ast::Module) -> Option<Runnable> {
@@ -62,7 +62,7 @@ fn runnable_mod(db: &RootDatabase, file_id: FileId, module: ast::Module) -> Opti
62 if !has_test_function { 62 if !has_test_function {
63 return None; 63 return None;
64 } 64 }
65 let range = module.syntax().range(); 65 let range = module.syntax().text_range();
66 let module = hir::source_binder::module_from_child_node(db, file_id, module.syntax())?; 66 let module = hir::source_binder::module_from_child_node(db, file_id, module.syntax())?;
67 67
68 let path = module.path_to_root(db).into_iter().rev().filter_map(|it| it.name(db)).join("::"); 68 let path = module.path_to_root(db).into_iter().rev().filter_map(|it| it.name(db)).join("::");
diff --git a/crates/ra_ide_api/src/symbol_index.rs b/crates/ra_ide_api/src/symbol_index.rs
index e784b5f69..d4afddab4 100644
--- a/crates/ra_ide_api/src/symbol_index.rs
+++ b/crates/ra_ide_api/src/symbol_index.rs
@@ -271,7 +271,7 @@ fn source_file_to_file_symbols(source_file: &SourceFile, file_id: FileId) -> Vec
271fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr, TextRange)> { 271fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr, TextRange)> {
272 fn decl<N: NameOwner>(node: N) -> Option<(SmolStr, SyntaxNodePtr, TextRange)> { 272 fn decl<N: NameOwner>(node: N) -> Option<(SmolStr, SyntaxNodePtr, TextRange)> {
273 let name = node.name()?; 273 let name = node.name()?;
274 let name_range = name.syntax().range(); 274 let name_range = name.syntax().text_range();
275 let name = name.text().clone(); 275 let name = name.text().clone();
276 let ptr = SyntaxNodePtr::new(node.syntax()); 276 let ptr = SyntaxNodePtr::new(node.syntax());
277 277
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs
index 477827fa7..878a94f06 100644
--- a/crates/ra_ide_api/src/syntax_highlighting.rs
+++ b/crates/ra_ide_api/src/syntax_highlighting.rs
@@ -189,11 +189,11 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa
189 if let Some(segment) = path.segment() { 189 if let Some(segment) = path.segment() {
190 if let Some(name_ref) = segment.name_ref() { 190 if let Some(name_ref) = segment.name_ref() {
191 highlighted.insert(name_ref.syntax().clone().into()); 191 highlighted.insert(name_ref.syntax().clone().into());
192 let range_start = name_ref.syntax().range().start(); 192 let range_start = name_ref.syntax().text_range().start();
193 let mut range_end = name_ref.syntax().range().end(); 193 let mut range_end = name_ref.syntax().text_range().end();
194 for sibling in path.syntax().siblings_with_tokens(Direction::Next) { 194 for sibling in path.syntax().siblings_with_tokens(Direction::Next) {
195 match sibling.kind() { 195 match sibling.kind() {
196 T![!] | IDENT => range_end = sibling.range().end(), 196 T![!] | IDENT => range_end = sibling.text_range().end(),
197 _ => (), 197 _ => (),
198 } 198 }
199 } 199 }
@@ -209,7 +209,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa
209 continue; 209 continue;
210 } 210 }
211 }; 211 };
212 res.push(HighlightedRange { range: node.range(), tag, binding_hash }) 212 res.push(HighlightedRange { range: node.text_range(), tag, binding_hash })
213 } 213 }
214 res 214 res
215} 215}
@@ -239,9 +239,9 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo
239 buf.push_str("<pre><code>"); 239 buf.push_str("<pre><code>");
240 let tokens = parse.tree().syntax().descendants_with_tokens().filter_map(|it| it.into_token()); 240 let tokens = parse.tree().syntax().descendants_with_tokens().filter_map(|it| it.into_token());
241 for token in tokens { 241 for token in tokens {
242 could_intersect.retain(|it| token.range().start() <= it.range.end()); 242 could_intersect.retain(|it| token.text_range().start() <= it.range.end());
243 while let Some(r) = ranges.get(frontier) { 243 while let Some(r) = ranges.get(frontier) {
244 if r.range.start() <= token.range().end() { 244 if r.range.start() <= token.text_range().end() {
245 could_intersect.push(r); 245 could_intersect.push(r);
246 frontier += 1; 246 frontier += 1;
247 } else { 247 } else {
@@ -251,7 +251,7 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo
251 let text = html_escape(&token.text()); 251 let text = html_escape(&token.text());
252 let ranges = could_intersect 252 let ranges = could_intersect
253 .iter() 253 .iter()
254 .filter(|it| token.range().is_subrange(&it.range)) 254 .filter(|it| token.text_range().is_subrange(&it.range))
255 .collect::<Vec<_>>(); 255 .collect::<Vec<_>>();
256 if ranges.is_empty() { 256 if ranges.is_empty() {
257 buf.push_str(&text); 257 buf.push_str(&text);
diff --git a/crates/ra_ide_api/src/syntax_tree.rs b/crates/ra_ide_api/src/syntax_tree.rs
index 3d7373d02..76c50f6d6 100644
--- a/crates/ra_ide_api/src/syntax_tree.rs
+++ b/crates/ra_ide_api/src/syntax_tree.rs
@@ -25,9 +25,9 @@ pub(crate) fn syntax_tree(
25 } 25 }
26 }; 26 };
27 27
28 node.debug_dump() 28 format!("{:#?}", node)
29 } else { 29 } else {
30 parse.tree().syntax().debug_dump() 30 format!("{:#?}", parse.tree().syntax())
31 } 31 }
32} 32}
33 33
@@ -45,7 +45,7 @@ fn syntax_tree_for_string(token: &SyntaxToken, text_range: TextRange) -> Option<
45 45
46fn syntax_tree_for_token(node: &SyntaxToken, text_range: TextRange) -> Option<String> { 46fn syntax_tree_for_token(node: &SyntaxToken, text_range: TextRange) -> Option<String> {
47 // Range of the full node 47 // Range of the full node
48 let node_range = node.range(); 48 let node_range = node.text_range();
49 let text = node.text().to_string(); 49 let text = node.text().to_string();
50 50
51 // We start at some point inside the node 51 // We start at some point inside the node
@@ -85,7 +85,7 @@ fn syntax_tree_for_token(node: &SyntaxToken, text_range: TextRange) -> Option<St
85 // If the "file" parsed without errors, 85 // If the "file" parsed without errors,
86 // return its syntax 86 // return its syntax
87 if parsed.errors().is_empty() { 87 if parsed.errors().is_empty() {
88 return Some(parsed.tree().syntax().debug_dump()); 88 return Some(format!("{:#?}", parsed.tree().syntax()));
89 } 89 }
90 90
91 None 91 None
diff --git a/crates/ra_ide_api/src/typing.rs b/crates/ra_ide_api/src/typing.rs
index ad0ababcc..1747a529e 100644
--- a/crates/ra_ide_api/src/typing.rs
+++ b/crates/ra_ide_api/src/typing.rs
@@ -24,7 +24,7 @@ pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<Sour
24 24
25 let prefix = comment.prefix(); 25 let prefix = comment.prefix();
26 if position.offset 26 if position.offset
27 < comment.syntax().range().start() + TextUnit::of_str(prefix) + TextUnit::from(1) 27 < comment.syntax().text_range().start() + TextUnit::of_str(prefix) + TextUnit::from(1)
28 { 28 {
29 return None; 29 return None;
30 } 30 }
@@ -45,7 +45,7 @@ pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<Sour
45} 45}
46 46
47fn node_indent(file: &SourceFile, token: &SyntaxToken) -> Option<SmolStr> { 47fn node_indent(file: &SourceFile, token: &SyntaxToken) -> Option<SmolStr> {
48 let ws = match find_token_at_offset(file.syntax(), token.range().start()) { 48 let ws = match find_token_at_offset(file.syntax(), token.text_range().start()) {
49 TokenAtOffset::Between(l, r) => { 49 TokenAtOffset::Between(l, r) => {
50 assert!(r == *token); 50 assert!(r == *token);
51 l 51 l
@@ -71,7 +71,7 @@ pub fn on_eq_typed(file: &SourceFile, eq_offset: TextUnit) -> Option<TextEdit> {
71 return None; 71 return None;
72 } 72 }
73 if let Some(expr) = let_stmt.initializer() { 73 if let Some(expr) = let_stmt.initializer() {
74 let expr_range = expr.syntax().range(); 74 let expr_range = expr.syntax().text_range();
75 if expr_range.contains(eq_offset) && eq_offset != expr_range.start() { 75 if expr_range.contains(eq_offset) && eq_offset != expr_range.start() {
76 return None; 76 return None;
77 } 77 }
@@ -81,7 +81,7 @@ pub fn on_eq_typed(file: &SourceFile, eq_offset: TextUnit) -> Option<TextEdit> {
81 } else { 81 } else {
82 return None; 82 return None;
83 } 83 }
84 let offset = let_stmt.syntax().range().end(); 84 let offset = let_stmt.syntax().text_range().end();
85 let mut edit = TextEditBuilder::default(); 85 let mut edit = TextEditBuilder::default();
86 edit.insert(offset, ";".to_string()); 86 edit.insert(offset, ";".to_string());
87 Some(edit.finish()) 87 Some(edit.finish())
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs
index 64ed6a517..7ff0fc472 100644
--- a/crates/ra_mbe/src/syntax_bridge.rs
+++ b/crates/ra_mbe/src/syntax_bridge.rs
@@ -19,7 +19,7 @@ pub struct TokenMap {
19pub fn ast_to_token_tree(ast: &ast::TokenTree) -> Option<(tt::Subtree, TokenMap)> { 19pub fn ast_to_token_tree(ast: &ast::TokenTree) -> Option<(tt::Subtree, TokenMap)> {
20 let mut token_map = TokenMap::default(); 20 let mut token_map = TokenMap::default();
21 let node = ast.syntax(); 21 let node = ast.syntax();
22 let tt = convert_tt(&mut token_map, node.range().start(), node)?; 22 let tt = convert_tt(&mut token_map, node.text_range().start(), node)?;
23 Some((tt, token_map)) 23 Some((tt, token_map))
24} 24}
25 25
@@ -27,7 +27,7 @@ pub fn ast_to_token_tree(ast: &ast::TokenTree) -> Option<(tt::Subtree, TokenMap)
27/// will consume). 27/// will consume).
28pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> Option<(tt::Subtree, TokenMap)> { 28pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> Option<(tt::Subtree, TokenMap)> {
29 let mut token_map = TokenMap::default(); 29 let mut token_map = TokenMap::default();
30 let tt = convert_tt(&mut token_map, node.range().start(), node)?; 30 let tt = convert_tt(&mut token_map, node.text_range().start(), node)?;
31 Some((tt, token_map)) 31 Some((tt, token_map))
32} 32}
33 33
@@ -229,7 +229,7 @@ fn convert_tt(
229 || token.kind() == IDENT 229 || token.kind() == IDENT
230 || token.kind() == LIFETIME 230 || token.kind() == LIFETIME
231 { 231 {
232 let relative_range = token.range() - global_offset; 232 let relative_range = token.text_range() - global_offset;
233 let id = token_map.alloc(relative_range); 233 let id = token_map.alloc(relative_range);
234 let text = token.text().clone(); 234 let text = token.text().clone();
235 tt::Leaf::from(tt::Ident { text, id }).into() 235 tt::Leaf::from(tt::Ident { text, id }).into()
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs
index 38a31109d..9151b6ecd 100644
--- a/crates/ra_mbe/src/tests.rs
+++ b/crates/ra_mbe/src/tests.rs
@@ -412,7 +412,7 @@ fn test_expand_to_item_list() {
412 let expansion = expand(&rules, "structs!(Foo, Bar);"); 412 let expansion = expand(&rules, "structs!(Foo, Bar);");
413 let tree = token_tree_to_macro_items(&expansion).unwrap().tree(); 413 let tree = token_tree_to_macro_items(&expansion).unwrap().tree();
414 assert_eq!( 414 assert_eq!(
415 tree.syntax().debug_dump().trim(), 415 format!("{:#?}", tree.syntax()).trim(),
416 r#" 416 r#"
417MACRO_ITEMS@[0; 40) 417MACRO_ITEMS@[0; 40)
418 STRUCT_DEF@[0; 20) 418 STRUCT_DEF@[0; 20)
@@ -531,7 +531,7 @@ fn test_tt_to_stmts() {
531 let stmts = token_tree_to_macro_stmts(&expanded).unwrap().tree(); 531 let stmts = token_tree_to_macro_stmts(&expanded).unwrap().tree();
532 532
533 assert_eq!( 533 assert_eq!(
534 stmts.syntax().debug_dump().trim(), 534 format!("{:#?}", stmts.syntax()).trim(),
535 r#"MACRO_STMTS@[0; 15) 535 r#"MACRO_STMTS@[0; 15)
536 LET_STMT@[0; 7) 536 LET_STMT@[0; 7)
537 LET_KW@[0; 3) "let" 537 LET_KW@[0; 3) "let"
@@ -669,7 +669,7 @@ fn test_expr_order() {
669 ); 669 );
670 670
671 assert_eq!( 671 assert_eq!(
672 expand_to_items(&rules, "foo! { 1 + 1 }").syntax().debug_dump().trim(), 672 format!("{:#?}", expand_to_items(&rules, "foo! { 1 + 1 }").syntax()).trim(),
673 r#"MACRO_ITEMS@[0; 15) 673 r#"MACRO_ITEMS@[0; 15)
674 FN_DEF@[0; 15) 674 FN_DEF@[0; 15)
675 FN_KW@[0; 2) "fn" 675 FN_KW@[0; 2) "fn"
@@ -1013,7 +1013,7 @@ fn test_vec() {
1013 ); 1013 );
1014 1014
1015 assert_eq!( 1015 assert_eq!(
1016 expand_to_expr(&rules, r#"vec![1u32,2];"#).syntax().debug_dump().trim(), 1016 format!("{:#?}", expand_to_expr(&rules, r#"vec![1u32,2];"#).syntax()).trim(),
1017 r#"BLOCK_EXPR@[0; 45) 1017 r#"BLOCK_EXPR@[0; 45)
1018 BLOCK@[0; 45) 1018 BLOCK@[0; 45)
1019 L_CURLY@[0; 1) "{" 1019 L_CURLY@[0; 1) "{"
diff --git a/crates/ra_syntax/src/algo.rs b/crates/ra_syntax/src/algo.rs
index e2de5e0e3..f47e11e66 100644
--- a/crates/ra_syntax/src/algo.rs
+++ b/crates/ra_syntax/src/algo.rs
@@ -25,7 +25,7 @@ pub fn ancestors_at_offset(
25) -> impl Iterator<Item = SyntaxNode> { 25) -> impl Iterator<Item = SyntaxNode> {
26 find_token_at_offset(node, offset) 26 find_token_at_offset(node, offset)
27 .map(|token| token.parent().ancestors()) 27 .map(|token| token.parent().ancestors())
28 .kmerge_by(|node1, node2| node1.range().len() < node2.range().len()) 28 .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len())
29} 29}
30 30
31/// Finds a node of specific Ast type at offset. Note that this is slightly 31/// Finds a node of specific Ast type at offset. Note that this is slightly
diff --git a/crates/ra_syntax/src/fuzz.rs b/crates/ra_syntax/src/fuzz.rs
index 716925b2f..698a624ec 100644
--- a/crates/ra_syntax/src/fuzz.rs
+++ b/crates/ra_syntax/src/fuzz.rs
@@ -51,10 +51,10 @@ impl CheckReparse {
51 for (a, b) in 51 for (a, b) in
52 new_parse.tree().syntax().descendants().zip(full_reparse.tree().syntax().descendants()) 52 new_parse.tree().syntax().descendants().zip(full_reparse.tree().syntax().descendants())
53 { 53 {
54 if (a.kind(), a.range()) != (b.kind(), b.range()) { 54 if (a.kind(), a.text_range()) != (b.kind(), b.text_range()) {
55 eprint!("original:\n{}", parse.tree().syntax().debug_dump()); 55 eprint!("original:\n{:#?}", parse.tree().syntax());
56 eprint!("reparsed:\n{}", new_parse.tree().syntax().debug_dump()); 56 eprint!("reparsed:\n{:#?}", new_parse.tree().syntax());
57 eprint!("full reparse:\n{}", full_reparse.tree().syntax().debug_dump()); 57 eprint!("full reparse:\n{:#?}", full_reparse.tree().syntax());
58 assert_eq!( 58 assert_eq!(
59 format!("{:?}", a), 59 format!("{:?}", a),
60 format!("{:?}", b), 60 format!("{:?}", b),
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs
index 604abe5c6..8af04c136 100644
--- a/crates/ra_syntax/src/lib.rs
+++ b/crates/ra_syntax/src/lib.rs
@@ -114,7 +114,7 @@ impl Parse<SyntaxNode> {
114 114
115impl Parse<SourceFile> { 115impl Parse<SourceFile> {
116 pub fn debug_dump(&self) -> String { 116 pub fn debug_dump(&self) -> String {
117 let mut buf = self.tree().syntax().debug_dump(); 117 let mut buf = format!("{:#?}", self.tree().syntax());
118 for err in self.errors.iter() { 118 for err in self.errors.iter() {
119 writeln!(buf, "error {:?}: {}", err.location(), err.kind()).unwrap(); 119 writeln!(buf, "error {:?}: {}", err.location(), err.kind()).unwrap();
120 } 120 }
@@ -234,7 +234,7 @@ fn api_walkthrough() {
234 assert_eq!(expr_syntax.kind(), SyntaxKind::BIN_EXPR); 234 assert_eq!(expr_syntax.kind(), SyntaxKind::BIN_EXPR);
235 235
236 // And text range: 236 // And text range:
237 assert_eq!(expr_syntax.range(), TextRange::from_to(32.into(), 37.into())); 237 assert_eq!(expr_syntax.text_range(), TextRange::from_to(32.into(), 37.into()));
238 238
239 // You can get node's text as a `SyntaxText` object, which will traverse the 239 // You can get node's text as a `SyntaxText` object, which will traverse the
240 // tree collecting token's text: 240 // tree collecting token's text:
diff --git a/crates/ra_syntax/src/parsing/reparsing.rs b/crates/ra_syntax/src/parsing/reparsing.rs
index b4ad9e019..2f388bdfe 100644
--- a/crates/ra_syntax/src/parsing/reparsing.rs
+++ b/crates/ra_syntax/src/parsing/reparsing.rs
@@ -46,7 +46,8 @@ fn reparse_token<'node>(
46 WHITESPACE | COMMENT | IDENT | STRING | RAW_STRING => { 46 WHITESPACE | COMMENT | IDENT | STRING | RAW_STRING => {
47 if token.kind() == WHITESPACE || token.kind() == COMMENT { 47 if token.kind() == WHITESPACE || token.kind() == COMMENT {
48 // removing a new line may extends previous token 48 // removing a new line may extends previous token
49 if token.text().to_string()[edit.delete - token.range().start()].contains('\n') { 49 if token.text().to_string()[edit.delete - token.text_range().start()].contains('\n')
50 {
50 return None; 51 return None;
51 } 52 }
52 } 53 }
@@ -62,7 +63,7 @@ fn reparse_token<'node>(
62 return None; 63 return None;
63 } 64 }
64 65
65 if let Some(next_char) = root.text().char_at(token.range().end()) { 66 if let Some(next_char) = root.text().char_at(token.text_range().end()) {
66 let tokens_with_next_char = tokenize(&format!("{}{}", text, next_char)); 67 let tokens_with_next_char = tokenize(&format!("{}{}", text, next_char));
67 if tokens_with_next_char.len() == 1 { 68 if tokens_with_next_char.len() == 1 {
68 return None; 69 return None;
@@ -70,7 +71,7 @@ fn reparse_token<'node>(
70 } 71 }
71 72
72 let new_token = GreenToken::new(rowan::SyntaxKind(token.kind().into()), text.into()); 73 let new_token = GreenToken::new(rowan::SyntaxKind(token.kind().into()), text.into());
73 Some((token.replace_with(new_token), token.range())) 74 Some((token.replace_with(new_token), token.text_range()))
74 } 75 }
75 _ => None, 76 _ => None,
76 } 77 }
@@ -90,11 +91,12 @@ fn reparse_block<'node>(
90 let mut tree_sink = TextTreeSink::new(&text, &tokens); 91 let mut tree_sink = TextTreeSink::new(&text, &tokens);
91 reparser.parse(&mut token_source, &mut tree_sink); 92 reparser.parse(&mut token_source, &mut tree_sink);
92 let (green, new_errors) = tree_sink.finish(); 93 let (green, new_errors) = tree_sink.finish();
93 Some((node.replace_with(green), new_errors, node.range())) 94 Some((node.replace_with(green), new_errors, node.text_range()))
94} 95}
95 96
96fn get_text_after_edit(element: SyntaxElement, edit: &AtomTextEdit) -> String { 97fn get_text_after_edit(element: SyntaxElement, edit: &AtomTextEdit) -> String {
97 let edit = AtomTextEdit::replace(edit.delete - element.range().start(), edit.insert.clone()); 98 let edit =
99 AtomTextEdit::replace(edit.delete - element.text_range().start(), edit.insert.clone());
98 let text = match element { 100 let text = match element {
99 SyntaxElement::Token(token) => token.text().to_string(), 101 SyntaxElement::Token(token) => token.text().to_string(),
100 SyntaxElement::Node(node) => node.text().to_string(), 102 SyntaxElement::Node(node) => node.text().to_string(),
@@ -188,8 +190,8 @@ mod tests {
188 }; 190 };
189 191
190 assert_eq_text!( 192 assert_eq_text!(
191 &fully_reparsed.tree().syntax().debug_dump(), 193 &format!("{:#?}", fully_reparsed.tree().syntax()),
192 &incrementally_reparsed.tree().syntax().debug_dump(), 194 &format!("{:#?}", incrementally_reparsed.tree().syntax()),
193 ); 195 );
194 } 196 }
195 197
diff --git a/crates/ra_syntax/src/ptr.rs b/crates/ra_syntax/src/ptr.rs
index d1b30a2c9..8665c8976 100644
--- a/crates/ra_syntax/src/ptr.rs
+++ b/crates/ra_syntax/src/ptr.rs
@@ -12,15 +12,15 @@ pub struct SyntaxNodePtr {
12 12
13impl SyntaxNodePtr { 13impl SyntaxNodePtr {
14 pub fn new(node: &SyntaxNode) -> SyntaxNodePtr { 14 pub fn new(node: &SyntaxNode) -> SyntaxNodePtr {
15 SyntaxNodePtr { range: node.range(), kind: node.kind() } 15 SyntaxNodePtr { range: node.text_range(), kind: node.kind() }
16 } 16 }
17 17
18 pub fn to_node(self, root: &SyntaxNode) -> SyntaxNode { 18 pub fn to_node(self, root: &SyntaxNode) -> SyntaxNode {
19 assert!(root.parent().is_none()); 19 assert!(root.parent().is_none());
20 successors(Some(root.clone()), |node| { 20 successors(Some(root.clone()), |node| {
21 node.children().find(|it| self.range.is_subrange(&it.range())) 21 node.children().find(|it| self.range.is_subrange(&it.text_range()))
22 }) 22 })
23 .find(|it| it.range() == self.range && it.kind() == self.kind) 23 .find(|it| it.text_range() == self.range && it.kind() == self.kind)
24 .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self)) 24 .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self))
25 } 25 }
26 26
diff --git a/crates/ra_syntax/src/syntax_node.rs b/crates/ra_syntax/src/syntax_node.rs
index 51bae04de..c42045d77 100644
--- a/crates/ra_syntax/src/syntax_node.rs
+++ b/crates/ra_syntax/src/syntax_node.rs
@@ -6,11 +6,7 @@
6//! The *real* implementation is in the (language-agnostic) `rowan` crate, this 6//! The *real* implementation is in the (language-agnostic) `rowan` crate, this
7//! modules just wraps its API. 7//! modules just wraps its API.
8 8
9use std::{ 9use std::{fmt, iter::successors, ops::RangeInclusive};
10 fmt::{self, Write},
11 iter::successors,
12 ops::RangeInclusive,
13};
14 10
15use ra_parser::ParseError; 11use ra_parser::ParseError;
16use rowan::GreenNodeBuilder; 12use rowan::GreenNodeBuilder;
@@ -36,8 +32,29 @@ pub enum InsertPosition<T> {
36pub struct SyntaxNode(pub(crate) rowan::cursor::SyntaxNode); 32pub struct SyntaxNode(pub(crate) rowan::cursor::SyntaxNode);
37 33
38impl fmt::Debug for SyntaxNode { 34impl fmt::Debug for SyntaxNode {
39 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 35 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
40 write!(fmt, "{:?}@{:?}", self.kind(), self.range()) 36 if f.alternate() {
37 let mut level = 0;
38 for event in self.preorder_with_tokens() {
39 match event {
40 WalkEvent::Enter(element) => {
41 for _ in 0..level {
42 write!(f, " ")?;
43 }
44 match element {
45 SyntaxElement::Node(node) => writeln!(f, "{:?}", node)?,
46 SyntaxElement::Token(token) => writeln!(f, "{:?}", token)?,
47 }
48 level += 1;
49 }
50 WalkEvent::Leave(_) => level -= 1,
51 }
52 }
53 assert_eq!(level, 0);
54 Ok(())
55 } else {
56 write!(f, "{:?}@{:?}", self.kind(), self.text_range())
57 }
41 } 58 }
42} 59}
43 60
@@ -63,7 +80,7 @@ impl SyntaxNode {
63 self.0.kind().0.into() 80 self.0.kind().0.into()
64 } 81 }
65 82
66 pub fn range(&self) -> TextRange { 83 pub fn text_range(&self) -> TextRange {
67 self.0.text_range() 84 self.0.text_range()
68 } 85 }
69 86
@@ -173,31 +190,6 @@ impl SyntaxNode {
173 }) 190 })
174 } 191 }
175 192
176 pub fn debug_dump(&self) -> String {
177 let mut level = 0;
178 let mut buf = String::new();
179
180 for event in self.preorder_with_tokens() {
181 match event {
182 WalkEvent::Enter(element) => {
183 for _ in 0..level {
184 buf.push_str(" ");
185 }
186 match element {
187 SyntaxElement::Node(node) => writeln!(buf, "{:?}", node).unwrap(),
188 SyntaxElement::Token(token) => writeln!(buf, "{:?}", token).unwrap(),
189 }
190 level += 1;
191 }
192 WalkEvent::Leave(_) => level -= 1,
193 }
194 }
195
196 assert_eq!(level, 0);
197
198 buf
199 }
200
201 pub(crate) fn replace_with(&self, replacement: GreenNode) -> GreenNode { 193 pub(crate) fn replace_with(&self, replacement: GreenNode) -> GreenNode {
202 self.0.replace_with(replacement) 194 self.0.replace_with(replacement)
203 } 195 }
@@ -299,7 +291,7 @@ pub struct SyntaxToken(pub(crate) rowan::cursor::SyntaxToken);
299 291
300impl fmt::Debug for SyntaxToken { 292impl fmt::Debug for SyntaxToken {
301 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 293 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
302 write!(fmt, "{:?}@{:?}", self.kind(), self.range())?; 294 write!(fmt, "{:?}@{:?}", self.kind(), self.text_range())?;
303 if self.text().len() < 25 { 295 if self.text().len() < 25 {
304 return write!(fmt, " {:?}", self.text()); 296 return write!(fmt, " {:?}", self.text());
305 } 297 }
@@ -329,7 +321,7 @@ impl SyntaxToken {
329 self.0.text() 321 self.0.text()
330 } 322 }
331 323
332 pub fn range(&self) -> TextRange { 324 pub fn text_range(&self) -> TextRange {
333 self.0.text_range() 325 self.0.text_range()
334 } 326 }
335 327
@@ -461,10 +453,10 @@ impl SyntaxElement {
461 .ancestors() 453 .ancestors()
462 } 454 }
463 455
464 pub fn range(&self) -> TextRange { 456 pub fn text_range(&self) -> TextRange {
465 match self { 457 match self {
466 SyntaxElement::Node(it) => it.range(), 458 SyntaxElement::Node(it) => it.text_range(),
467 SyntaxElement::Token(it) => it.range(), 459 SyntaxElement::Token(it) => it.text_range(),
468 } 460 }
469 } 461 }
470 462
diff --git a/crates/ra_syntax/src/syntax_text.rs b/crates/ra_syntax/src/syntax_text.rs
index 2ad98809b..f8ddff48e 100644
--- a/crates/ra_syntax/src/syntax_text.rs
+++ b/crates/ra_syntax/src/syntax_text.rs
@@ -13,7 +13,7 @@ pub struct SyntaxText {
13 13
14impl SyntaxText { 14impl SyntaxText {
15 pub(crate) fn new(node: SyntaxNode) -> SyntaxText { 15 pub(crate) fn new(node: SyntaxNode) -> SyntaxText {
16 let range = node.range(); 16 let range = node.text_range();
17 SyntaxText { node, range } 17 SyntaxText { node, range }
18 } 18 }
19 19
@@ -24,14 +24,14 @@ impl SyntaxText {
24 self.node.descendants_with_tokens().try_fold(init, move |acc, element| { 24 self.node.descendants_with_tokens().try_fold(init, move |acc, element| {
25 let res = match element { 25 let res = match element {
26 SyntaxElement::Token(token) => { 26 SyntaxElement::Token(token) => {
27 let range = match self.range.intersection(&token.range()) { 27 let range = match self.range.intersection(&token.text_range()) {
28 None => return Ok(acc), 28 None => return Ok(acc),
29 Some(it) => it, 29 Some(it) => it,
30 }; 30 };
31 let slice = if range == token.range() { 31 let slice = if range == token.text_range() {
32 token.text() 32 token.text()
33 } else { 33 } else {
34 let range = range - token.range().start(); 34 let range = range - token.text_range().start();
35 &token.text()[range] 35 &token.text()[range]
36 }; 36 };
37 f(acc, slice)? 37 f(acc, slice)?
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs
index 7140d10c3..19bdafef2 100644
--- a/crates/ra_syntax/src/validation.rs
+++ b/crates/ra_syntax/src/validation.rs
@@ -33,7 +33,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
33 if let Some(end) = text.rfind('\'') { 33 if let Some(end) = text.rfind('\'') {
34 if let Some(without_quotes) = text.get(2..end) { 34 if let Some(without_quotes) = text.get(2..end) {
35 if let Err((off, err)) = unescape::unescape_byte(without_quotes) { 35 if let Err((off, err)) = unescape::unescape_byte(without_quotes) {
36 let off = token.range().start() + TextUnit::from_usize(off + 2); 36 let off = token.text_range().start() + TextUnit::from_usize(off + 2);
37 acc.push(SyntaxError::new(err.into(), off)) 37 acc.push(SyntaxError::new(err.into(), off))
38 } 38 }
39 } 39 }
@@ -43,7 +43,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
43 if let Some(end) = text.rfind('\'') { 43 if let Some(end) = text.rfind('\'') {
44 if let Some(without_quotes) = text.get(1..end) { 44 if let Some(without_quotes) = text.get(1..end) {
45 if let Err((off, err)) = unescape::unescape_char(without_quotes) { 45 if let Err((off, err)) = unescape::unescape_char(without_quotes) {
46 let off = token.range().start() + TextUnit::from_usize(off + 1); 46 let off = token.text_range().start() + TextUnit::from_usize(off + 1);
47 acc.push(SyntaxError::new(err.into(), off)) 47 acc.push(SyntaxError::new(err.into(), off))
48 } 48 }
49 } 49 }
@@ -55,7 +55,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
55 unescape::unescape_byte_str(without_quotes, &mut |range, char| { 55 unescape::unescape_byte_str(without_quotes, &mut |range, char| {
56 if let Err(err) = char { 56 if let Err(err) = char {
57 let off = range.start; 57 let off = range.start;
58 let off = token.range().start() + TextUnit::from_usize(off + 2); 58 let off = token.text_range().start() + TextUnit::from_usize(off + 2);
59 acc.push(SyntaxError::new(err.into(), off)) 59 acc.push(SyntaxError::new(err.into(), off))
60 } 60 }
61 }) 61 })
@@ -68,7 +68,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
68 unescape::unescape_str(without_quotes, &mut |range, char| { 68 unescape::unescape_str(without_quotes, &mut |range, char| {
69 if let Err(err) = char { 69 if let Err(err) = char {
70 let off = range.start; 70 let off = range.start;
71 let off = token.range().start() + TextUnit::from_usize(off + 1); 71 let off = token.text_range().start() + TextUnit::from_usize(off + 1);
72 acc.push(SyntaxError::new(err.into(), off)) 72 acc.push(SyntaxError::new(err.into(), off))
73 } 73 }
74 }) 74 })
@@ -89,9 +89,9 @@ pub(crate) fn validate_block_structure(root: &SyntaxNode) {
89 assert_eq!( 89 assert_eq!(
90 node.parent(), 90 node.parent(),
91 pair.parent(), 91 pair.parent(),
92 "\nunpaired curleys:\n{}\n{}\n", 92 "\nunpaired curleys:\n{}\n{:#?}\n",
93 root.text(), 93 root.text(),
94 root.debug_dump(), 94 root,
95 ); 95 );
96 assert!( 96 assert!(
97 node.next_sibling().is_none() && pair.prev_sibling().is_none(), 97 node.next_sibling().is_none() && pair.prev_sibling().is_none(),
diff --git a/crates/ra_syntax/src/validation/block.rs b/crates/ra_syntax/src/validation/block.rs
index f5573bd8f..c5588658d 100644
--- a/crates/ra_syntax/src/validation/block.rs
+++ b/crates/ra_syntax/src/validation/block.rs
@@ -16,6 +16,7 @@ pub(crate) fn validate_block_node(node: ast::Block, errors: &mut Vec<SyntaxError
16 _ => {} 16 _ => {}
17 } 17 }
18 } 18 }
19 errors 19 errors.extend(
20 .extend(node.attrs().map(|attr| SyntaxError::new(InvalidBlockAttr, attr.syntax().range()))) 20 node.attrs().map(|attr| SyntaxError::new(InvalidBlockAttr, attr.syntax().text_range())),
21 )
21} 22}
diff --git a/crates/ra_syntax/src/validation/field_expr.rs b/crates/ra_syntax/src/validation/field_expr.rs
index 0e18bd9ca..004f199fd 100644
--- a/crates/ra_syntax/src/validation/field_expr.rs
+++ b/crates/ra_syntax/src/validation/field_expr.rs
@@ -7,7 +7,7 @@ use crate::{
7pub(crate) fn validate_field_expr_node(node: ast::FieldExpr, errors: &mut Vec<SyntaxError>) { 7pub(crate) fn validate_field_expr_node(node: ast::FieldExpr, errors: &mut Vec<SyntaxError>) {
8 if let Some(FieldKind::Index(idx)) = node.field_access() { 8 if let Some(FieldKind::Index(idx)) = node.field_access() {
9 if idx.text().chars().any(|c| c < '0' || c > '9') { 9 if idx.text().chars().any(|c| c < '0' || c > '9') {
10 errors.push(SyntaxError::new(InvalidTupleIndexFormat, idx.range())); 10 errors.push(SyntaxError::new(InvalidTupleIndexFormat, idx.text_range()));
11 } 11 }
12 } 12 }
13} 13}