mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 01:04:03 +00:00
Merge #1560
1560: move debug_dump to fmt::Debug r=matklad a=matklad Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
6b352ffeb3
@ -22,9 +22,9 @@ pub(crate) fn add_derive(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist>
|
|||||||
edit.insert(node_start, "#[derive()]\n");
|
edit.insert(node_start, "#[derive()]\n");
|
||||||
node_start + TextUnit::of_str("#[derive(")
|
node_start + TextUnit::of_str("#[derive(")
|
||||||
}
|
}
|
||||||
Some(tt) => tt.syntax().range().end() - TextUnit::of_char(')'),
|
Some(tt) => tt.syntax().text_range().end() - TextUnit::of_char(')'),
|
||||||
};
|
};
|
||||||
edit.target(nominal.syntax().range());
|
edit.target(nominal.syntax().text_range());
|
||||||
edit.set_cursor(offset)
|
edit.set_cursor(offset)
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ fn derive_insertion_offset(nominal: &ast::NominalDef) -> Option<TextUnit> {
|
|||||||
.syntax()
|
.syntax()
|
||||||
.children_with_tokens()
|
.children_with_tokens()
|
||||||
.find(|it| it.kind() != COMMENT && it.kind() != WHITESPACE)?;
|
.find(|it| it.kind() != COMMENT && it.kind() != WHITESPACE)?;
|
||||||
Some(non_ws_child.range().start())
|
Some(non_ws_child.text_range().start())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -16,10 +16,10 @@ pub(crate) fn add_explicit_type(mut ctx: AssistCtx<impl HirDatabase>) -> Option<
|
|||||||
PatKind::BindPat(bind_pat) => bind_pat,
|
PatKind::BindPat(bind_pat) => bind_pat,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
let pat_range = pat.syntax().range();
|
let pat_range = pat.syntax().text_range();
|
||||||
// The binding must have a name
|
// The binding must have a name
|
||||||
let name = pat.name()?;
|
let name = pat.name()?;
|
||||||
let name_range = name.syntax().range();
|
let name_range = name.syntax().text_range();
|
||||||
// Assist not applicable if the type has already been specified
|
// Assist not applicable if the type has already been specified
|
||||||
if stmt.syntax().children_with_tokens().any(|child| child.kind() == T![:]) {
|
if stmt.syntax().children_with_tokens().any(|child| child.kind() == T![:]) {
|
||||||
return None;
|
return None;
|
||||||
|
@ -11,9 +11,9 @@ pub(crate) fn add_impl(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
|||||||
let nominal = ctx.node_at_offset::<ast::NominalDef>()?;
|
let nominal = ctx.node_at_offset::<ast::NominalDef>()?;
|
||||||
let name = nominal.name()?;
|
let name = nominal.name()?;
|
||||||
ctx.add_action(AssistId("add_impl"), "add impl", |edit| {
|
ctx.add_action(AssistId("add_impl"), "add impl", |edit| {
|
||||||
edit.target(nominal.syntax().range());
|
edit.target(nominal.syntax().text_range());
|
||||||
let type_params = nominal.type_param_list();
|
let type_params = nominal.type_param_list();
|
||||||
let start_offset = nominal.syntax().range().end();
|
let start_offset = nominal.syntax().text_range().end();
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
buf.push_str("\n\nimpl");
|
buf.push_str("\n\nimpl");
|
||||||
if let Some(type_params) = &type_params {
|
if let Some(type_params) = &type_params {
|
||||||
|
@ -43,7 +43,7 @@ fn add_missing_impl_members_inner(
|
|||||||
|
|
||||||
let trait_def = {
|
let trait_def = {
|
||||||
let file_id = ctx.frange.file_id;
|
let file_id = ctx.frange.file_id;
|
||||||
let position = FilePosition { file_id, offset: impl_node.syntax().range().start() };
|
let position = FilePosition { file_id, offset: impl_node.syntax().text_range().start() };
|
||||||
let analyzer = hir::SourceAnalyzer::new(ctx.db, position.file_id, impl_node.syntax(), None);
|
let analyzer = hir::SourceAnalyzer::new(ctx.db, position.file_id, impl_node.syntax(), None);
|
||||||
|
|
||||||
resolve_target_trait_def(ctx.db, &analyzer, &impl_node)?
|
resolve_target_trait_def(ctx.db, &analyzer, &impl_node)?
|
||||||
@ -87,7 +87,7 @@ fn add_missing_impl_members_inner(
|
|||||||
ast_editor.append_items(items);
|
ast_editor.append_items(items);
|
||||||
|
|
||||||
let first_new_item = ast_editor.ast().impl_items().nth(n_existing_items).unwrap();
|
let first_new_item = ast_editor.ast().impl_items().nth(n_existing_items).unwrap();
|
||||||
let cursor_position = first_new_item.syntax().range().start();
|
let cursor_position = first_new_item.syntax().text_range().start();
|
||||||
ast_editor.into_text_edit(edit.text_edit_builder());
|
ast_editor.into_text_edit(edit.text_edit_builder());
|
||||||
|
|
||||||
edit.set_cursor(cursor_position);
|
edit.set_cursor(cursor_position);
|
||||||
|
@ -141,7 +141,7 @@ impl AssistBuilder {
|
|||||||
if let Some(indent) = leading_indent(node) {
|
if let Some(indent) = leading_indent(node) {
|
||||||
replace_with = reindent(&replace_with, &indent)
|
replace_with = reindent(&replace_with, &indent)
|
||||||
}
|
}
|
||||||
self.replace(node.range(), replace_with)
|
self.replace(node.text_range(), replace_with)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_edit_builder(&mut self, edit: TextEditBuilder) {
|
pub(crate) fn set_edit_builder(&mut self, edit: TextEditBuilder) {
|
||||||
|
@ -22,7 +22,10 @@ impl<N: AstNode> AstEditor<N> {
|
|||||||
// FIXME: compute a more fine-grained diff here.
|
// FIXME: compute a more fine-grained diff here.
|
||||||
// If *you* know a nice algorithm to compute diff between two syntax
|
// If *you* know a nice algorithm to compute diff between two syntax
|
||||||
// tree, tell me about it!
|
// tree, tell me about it!
|
||||||
builder.replace(self.original_ast.syntax().range(), self.ast().syntax().text().to_string());
|
builder.replace(
|
||||||
|
self.original_ast.syntax().text_range(),
|
||||||
|
self.ast().syntax().text().to_string(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ast(&self) -> &N {
|
pub fn ast(&self) -> &N {
|
||||||
|
@ -356,7 +356,7 @@ fn best_action_for_target(
|
|||||||
// todo: we should include even whitespace blocks as anchor candidates
|
// todo: we should include even whitespace blocks as anchor candidates
|
||||||
let anchor = container
|
let anchor = container
|
||||||
.children()
|
.children()
|
||||||
.find(|n| n.range().start() < anchor.range().start())
|
.find(|n| n.text_range().start() < anchor.text_range().start())
|
||||||
.or_else(|| Some(anchor));
|
.or_else(|| Some(anchor));
|
||||||
|
|
||||||
ImportAction::add_new_use(anchor, false)
|
ImportAction::add_new_use(anchor, false)
|
||||||
@ -418,7 +418,7 @@ fn make_assist_add_new_use(
|
|||||||
buf.push_str(&spaces);
|
buf.push_str(&spaces);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let position = if after { anchor.range().end() } else { anchor.range().start() };
|
let position = if after { anchor.text_range().end() } else { anchor.text_range().start() };
|
||||||
edit.insert(position, buf);
|
edit.insert(position, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -434,10 +434,10 @@ fn make_assist_add_in_tree_list(
|
|||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
let comma = last.syntax().siblings(Direction::Next).find(|n| n.kind() == T![,]);
|
let comma = last.syntax().siblings(Direction::Next).find(|n| n.kind() == T![,]);
|
||||||
let offset = if let Some(comma) = comma {
|
let offset = if let Some(comma) = comma {
|
||||||
comma.range().end()
|
comma.text_range().end()
|
||||||
} else {
|
} else {
|
||||||
buf.push_str(",");
|
buf.push_str(",");
|
||||||
last.syntax().range().end()
|
last.syntax().text_range().end()
|
||||||
};
|
};
|
||||||
if add_self {
|
if add_self {
|
||||||
buf.push_str(" self")
|
buf.push_str(" self")
|
||||||
@ -462,11 +462,11 @@ fn make_assist_add_nested_import(
|
|||||||
if let Some(use_tree) = use_tree {
|
if let Some(use_tree) = use_tree {
|
||||||
let (start, add_colon_colon) = if let Some(first_segment_to_split) = first_segment_to_split
|
let (start, add_colon_colon) = if let Some(first_segment_to_split) = first_segment_to_split
|
||||||
{
|
{
|
||||||
(first_segment_to_split.syntax().range().start(), false)
|
(first_segment_to_split.syntax().text_range().start(), false)
|
||||||
} else {
|
} else {
|
||||||
(use_tree.syntax().range().end(), true)
|
(use_tree.syntax().text_range().end(), true)
|
||||||
};
|
};
|
||||||
let end = use_tree.syntax().range().end();
|
let end = use_tree.syntax().text_range().end();
|
||||||
|
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
if add_colon_colon {
|
if add_colon_colon {
|
||||||
@ -497,8 +497,8 @@ fn apply_auto_import(
|
|||||||
// Here we are assuming the assist will provide a correct use statement
|
// Here we are assuming the assist will provide a correct use statement
|
||||||
// so we can delete the path qualifier
|
// so we can delete the path qualifier
|
||||||
edit.delete(TextRange::from_to(
|
edit.delete(TextRange::from_to(
|
||||||
path.syntax().range().start(),
|
path.syntax().text_range().start(),
|
||||||
last.syntax().range().start(),
|
last.syntax().text_range().start(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,14 +35,15 @@ fn add_vis(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
|||||||
if parent.children().any(|child| child.kind() == VISIBILITY) {
|
if parent.children().any(|child| child.kind() == VISIBILITY) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
(vis_offset(&parent), keyword.range())
|
(vis_offset(&parent), keyword.text_range())
|
||||||
} else {
|
} else {
|
||||||
let ident = ctx.token_at_offset().find(|leaf| leaf.kind() == IDENT)?;
|
let ident = ctx.token_at_offset().find(|leaf| leaf.kind() == IDENT)?;
|
||||||
let field = ident.parent().ancestors().find_map(ast::NamedFieldDef::cast)?;
|
let field = ident.parent().ancestors().find_map(ast::NamedFieldDef::cast)?;
|
||||||
if field.name()?.syntax().range() != ident.range() && field.visibility().is_some() {
|
if field.name()?.syntax().text_range() != ident.text_range() && field.visibility().is_some()
|
||||||
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
(vis_offset(field.syntax()), ident.range())
|
(vis_offset(field.syntax()), ident.text_range())
|
||||||
};
|
};
|
||||||
|
|
||||||
ctx.add_action(AssistId("change_visibility"), "make pub(crate)", |edit| {
|
ctx.add_action(AssistId("change_visibility"), "make pub(crate)", |edit| {
|
||||||
@ -61,25 +62,25 @@ fn vis_offset(node: &SyntaxNode) -> TextUnit {
|
|||||||
_ => false,
|
_ => false,
|
||||||
})
|
})
|
||||||
.next()
|
.next()
|
||||||
.map(|it| it.range().start())
|
.map(|it| it.text_range().start())
|
||||||
.unwrap_or_else(|| node.range().start())
|
.unwrap_or_else(|| node.text_range().start())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_vis(mut ctx: AssistCtx<impl HirDatabase>, vis: ast::Visibility) -> Option<Assist> {
|
fn change_vis(mut ctx: AssistCtx<impl HirDatabase>, vis: ast::Visibility) -> Option<Assist> {
|
||||||
if vis.syntax().text() == "pub" {
|
if vis.syntax().text() == "pub" {
|
||||||
ctx.add_action(AssistId("change_visibility"), "change to pub(crate)", |edit| {
|
ctx.add_action(AssistId("change_visibility"), "change to pub(crate)", |edit| {
|
||||||
edit.target(vis.syntax().range());
|
edit.target(vis.syntax().text_range());
|
||||||
edit.replace(vis.syntax().range(), "pub(crate)");
|
edit.replace(vis.syntax().text_range(), "pub(crate)");
|
||||||
edit.set_cursor(vis.syntax().range().start())
|
edit.set_cursor(vis.syntax().text_range().start())
|
||||||
});
|
});
|
||||||
|
|
||||||
return ctx.build();
|
return ctx.build();
|
||||||
}
|
}
|
||||||
if vis.syntax().text() == "pub(crate)" {
|
if vis.syntax().text() == "pub(crate)" {
|
||||||
ctx.add_action(AssistId("change_visibility"), "change to pub", |edit| {
|
ctx.add_action(AssistId("change_visibility"), "change to pub", |edit| {
|
||||||
edit.target(vis.syntax().range());
|
edit.target(vis.syntax().text_range());
|
||||||
edit.replace(vis.syntax().range(), "pub");
|
edit.replace(vis.syntax().text_range(), "pub");
|
||||||
edit.set_cursor(vis.syntax().range().start());
|
edit.set_cursor(vis.syntax().text_range().start());
|
||||||
});
|
});
|
||||||
|
|
||||||
return ctx.build();
|
return ctx.build();
|
||||||
|
@ -84,8 +84,8 @@ pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<As
|
|||||||
buf.push_str(" => (),\n");
|
buf.push_str(" => (),\n");
|
||||||
}
|
}
|
||||||
buf.push_str("}");
|
buf.push_str("}");
|
||||||
edit.target(match_expr.syntax().range());
|
edit.target(match_expr.syntax().text_range());
|
||||||
edit.set_cursor(expr.syntax().range().start());
|
edit.set_cursor(expr.syntax().text_range().start());
|
||||||
edit.replace_node_and_indent(match_expr.syntax(), buf);
|
edit.replace_node_and_indent(match_expr.syntax(), buf);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ pub(crate) fn flip_binexpr(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assis
|
|||||||
let expr = ctx.node_at_offset::<BinExpr>()?;
|
let expr = ctx.node_at_offset::<BinExpr>()?;
|
||||||
let lhs = expr.lhs()?.syntax().clone();
|
let lhs = expr.lhs()?.syntax().clone();
|
||||||
let rhs = expr.rhs()?.syntax().clone();
|
let rhs = expr.rhs()?.syntax().clone();
|
||||||
let op_range = expr.op_token()?.range();
|
let op_range = expr.op_token()?.text_range();
|
||||||
// The assist should be applied only if the cursor is on the operator
|
// The assist should be applied only if the cursor is on the operator
|
||||||
let cursor_in_range = ctx.frange.range.is_subrange(&op_range);
|
let cursor_in_range = ctx.frange.range.is_subrange(&op_range);
|
||||||
if !cursor_in_range {
|
if !cursor_in_range {
|
||||||
@ -25,8 +25,8 @@ pub(crate) fn flip_binexpr(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assis
|
|||||||
if let FlipAction::FlipAndReplaceOp(new_op) = action {
|
if let FlipAction::FlipAndReplaceOp(new_op) = action {
|
||||||
edit.replace(op_range, new_op);
|
edit.replace(op_range, new_op);
|
||||||
}
|
}
|
||||||
edit.replace(lhs.range(), rhs.text());
|
edit.replace(lhs.text_range(), rhs.text());
|
||||||
edit.replace(rhs.range(), lhs.text());
|
edit.replace(rhs.text_range(), lhs.text());
|
||||||
});
|
});
|
||||||
|
|
||||||
ctx.build()
|
ctx.build()
|
||||||
|
@ -8,9 +8,9 @@ pub(crate) fn flip_comma(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist>
|
|||||||
let prev = non_trivia_sibling(comma.clone().into(), Direction::Prev)?;
|
let prev = non_trivia_sibling(comma.clone().into(), Direction::Prev)?;
|
||||||
let next = non_trivia_sibling(comma.clone().into(), Direction::Next)?;
|
let next = non_trivia_sibling(comma.clone().into(), Direction::Next)?;
|
||||||
ctx.add_action(AssistId("flip_comma"), "flip comma", |edit| {
|
ctx.add_action(AssistId("flip_comma"), "flip comma", |edit| {
|
||||||
edit.target(comma.range());
|
edit.target(comma.text_range());
|
||||||
edit.replace(prev.range(), next.to_string());
|
edit.replace(prev.text_range(), next.to_string());
|
||||||
edit.replace(next.range(), prev.to_string());
|
edit.replace(next.text_range(), prev.to_string());
|
||||||
});
|
});
|
||||||
|
|
||||||
ctx.build()
|
ctx.build()
|
||||||
|
@ -22,9 +22,12 @@ pub(crate) fn inline_local_varialbe(mut ctx: AssistCtx<impl HirDatabase>) -> Opt
|
|||||||
.next_sibling_or_token()
|
.next_sibling_or_token()
|
||||||
.and_then(|it| ast::Whitespace::cast(it.as_token()?.clone()))
|
.and_then(|it| ast::Whitespace::cast(it.as_token()?.clone()))
|
||||||
{
|
{
|
||||||
TextRange::from_to(let_stmt.syntax().range().start(), whitespace.syntax().range().end())
|
TextRange::from_to(
|
||||||
|
let_stmt.syntax().text_range().start(),
|
||||||
|
whitespace.syntax().text_range().end(),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
let_stmt.syntax().range()
|
let_stmt.syntax().text_range()
|
||||||
};
|
};
|
||||||
let analyzer = hir::SourceAnalyzer::new(ctx.db, ctx.frange.file_id, bind_pat.syntax(), None);
|
let analyzer = hir::SourceAnalyzer::new(ctx.db, ctx.frange.file_id, bind_pat.syntax(), None);
|
||||||
let refs = analyzer.find_all_refs(&bind_pat);
|
let refs = analyzer.find_all_refs(&bind_pat);
|
||||||
|
@ -48,7 +48,7 @@ pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option
|
|||||||
if !full_stmt.unwrap().has_semi() {
|
if !full_stmt.unwrap().has_semi() {
|
||||||
buf.push_str(";");
|
buf.push_str(";");
|
||||||
}
|
}
|
||||||
edit.replace(expr.syntax().range(), buf);
|
edit.replace(expr.syntax().text_range(), buf);
|
||||||
} else {
|
} else {
|
||||||
buf.push_str(";");
|
buf.push_str(";");
|
||||||
|
|
||||||
@ -66,14 +66,14 @@ pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option
|
|||||||
buf.push_str(text);
|
buf.push_str(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
edit.target(expr.syntax().range());
|
edit.target(expr.syntax().text_range());
|
||||||
edit.replace(expr.syntax().range(), "var_name".to_string());
|
edit.replace(expr.syntax().text_range(), "var_name".to_string());
|
||||||
edit.insert(anchor_stmt.range().start(), buf);
|
edit.insert(anchor_stmt.text_range().start(), buf);
|
||||||
if wrap_in_block {
|
if wrap_in_block {
|
||||||
edit.insert(anchor_stmt.range().end(), " }");
|
edit.insert(anchor_stmt.text_range().end(), " }");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
edit.set_cursor(anchor_stmt.range().start() + cursor_offset);
|
edit.set_cursor(anchor_stmt.text_range().start() + cursor_offset);
|
||||||
});
|
});
|
||||||
|
|
||||||
ctx.build()
|
ctx.build()
|
||||||
|
@ -17,11 +17,11 @@ pub(crate) fn move_guard_to_arm_body(mut ctx: AssistCtx<impl HirDatabase>) -> Op
|
|||||||
let buf = format!("if {} {{ {} }}", guard_conditions.syntax().text(), arm_expr.syntax().text());
|
let buf = format!("if {} {{ {} }}", guard_conditions.syntax().text(), arm_expr.syntax().text());
|
||||||
|
|
||||||
ctx.add_action(AssistId("move_guard_to_arm_body"), "move guard to arm body", |edit| {
|
ctx.add_action(AssistId("move_guard_to_arm_body"), "move guard to arm body", |edit| {
|
||||||
edit.target(guard.syntax().range());
|
edit.target(guard.syntax().text_range());
|
||||||
let offseting_amount = match &space_before_guard {
|
let offseting_amount = match &space_before_guard {
|
||||||
Some(SyntaxElement::Token(tok)) => {
|
Some(SyntaxElement::Token(tok)) => {
|
||||||
if let Some(_) = ast::Whitespace::cast(tok.clone()) {
|
if let Some(_) = ast::Whitespace::cast(tok.clone()) {
|
||||||
let ele = space_before_guard.unwrap().range();
|
let ele = space_before_guard.unwrap().text_range();
|
||||||
edit.delete(ele);
|
edit.delete(ele);
|
||||||
ele.len()
|
ele.len()
|
||||||
} else {
|
} else {
|
||||||
@ -31,9 +31,11 @@ pub(crate) fn move_guard_to_arm_body(mut ctx: AssistCtx<impl HirDatabase>) -> Op
|
|||||||
_ => TextUnit::from(0),
|
_ => TextUnit::from(0),
|
||||||
};
|
};
|
||||||
|
|
||||||
edit.delete(guard.syntax().range());
|
edit.delete(guard.syntax().text_range());
|
||||||
edit.replace_node_and_indent(arm_expr.syntax(), buf);
|
edit.replace_node_and_indent(arm_expr.syntax(), buf);
|
||||||
edit.set_cursor(arm_expr.syntax().range().start() + TextUnit::from(3) - offseting_amount);
|
edit.set_cursor(
|
||||||
|
arm_expr.syntax().text_range().start() + TextUnit::from(3) - offseting_amount,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
ctx.build()
|
ctx.build()
|
||||||
}
|
}
|
||||||
@ -62,18 +64,18 @@ pub(crate) fn move_arm_cond_to_match_guard(mut ctx: AssistCtx<impl HirDatabase>)
|
|||||||
AssistId("move_arm_cond_to_match_guard"),
|
AssistId("move_arm_cond_to_match_guard"),
|
||||||
"move condition to match guard",
|
"move condition to match guard",
|
||||||
|edit| {
|
|edit| {
|
||||||
edit.target(if_expr.syntax().range());
|
edit.target(if_expr.syntax().text_range());
|
||||||
let then_only_expr = then_block.statements().next().is_none();
|
let then_only_expr = then_block.statements().next().is_none();
|
||||||
|
|
||||||
match &then_block.expr() {
|
match &then_block.expr() {
|
||||||
Some(then_expr) if then_only_expr => {
|
Some(then_expr) if then_only_expr => {
|
||||||
edit.replace(if_expr.syntax().range(), then_expr.syntax().text())
|
edit.replace(if_expr.syntax().text_range(), then_expr.syntax().text())
|
||||||
}
|
}
|
||||||
_ => edit.replace(if_expr.syntax().range(), then_block.syntax().text()),
|
_ => edit.replace(if_expr.syntax().text_range(), then_block.syntax().text()),
|
||||||
}
|
}
|
||||||
|
|
||||||
edit.insert(last_match_pat.syntax().range().end(), buf);
|
edit.insert(last_match_pat.syntax().text_range().end(), buf);
|
||||||
edit.set_cursor(last_match_pat.syntax().range().end() + TextUnit::from(1));
|
edit.set_cursor(last_match_pat.syntax().text_range().end() + TextUnit::from(1));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
ctx.build()
|
ctx.build()
|
||||||
|
@ -12,7 +12,7 @@ pub(crate) fn remove_dbg(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist>
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let macro_range = macro_call.syntax().range();
|
let macro_range = macro_call.syntax().text_range();
|
||||||
|
|
||||||
// If the cursor is inside the macro call, we'll try to maintain the cursor
|
// If the cursor is inside the macro call, we'll try to maintain the cursor
|
||||||
// position by subtracting the length of dbg!( from the start of the file
|
// 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>
|
|||||||
};
|
};
|
||||||
|
|
||||||
ctx.add_action(AssistId("remove_dbg"), "remove dbg!()", |edit| {
|
ctx.add_action(AssistId("remove_dbg"), "remove dbg!()", |edit| {
|
||||||
edit.target(macro_call.syntax().range());
|
edit.target(macro_call.syntax().text_range());
|
||||||
edit.replace(macro_range, macro_content);
|
edit.replace(macro_range, macro_content);
|
||||||
edit.set_cursor(cursor_pos);
|
edit.set_cursor(cursor_pos);
|
||||||
});
|
});
|
||||||
|
@ -17,9 +17,9 @@ pub(crate) fn replace_if_let_with_match(mut ctx: AssistCtx<impl HirDatabase>) ->
|
|||||||
|
|
||||||
ctx.add_action(AssistId("replace_if_let_with_match"), "replace with match", |edit| {
|
ctx.add_action(AssistId("replace_if_let_with_match"), "replace with match", |edit| {
|
||||||
let match_expr = build_match_expr(expr, pat, then_block, else_block);
|
let match_expr = build_match_expr(expr, pat, then_block, else_block);
|
||||||
edit.target(if_expr.syntax().range());
|
edit.target(if_expr.syntax().text_range());
|
||||||
edit.replace_node_and_indent(if_expr.syntax(), match_expr);
|
edit.replace_node_and_indent(if_expr.syntax(), match_expr);
|
||||||
edit.set_cursor(if_expr.syntax().range().start())
|
edit.set_cursor(if_expr.syntax().text_range().start())
|
||||||
});
|
});
|
||||||
|
|
||||||
ctx.build()
|
ctx.build()
|
||||||
|
@ -15,14 +15,14 @@ pub(crate) fn split_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assis
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let l_curly = colon_colon.range().end();
|
let l_curly = colon_colon.text_range().end();
|
||||||
let r_curly = match top_path.syntax().parent().and_then(ast::UseTree::cast) {
|
let r_curly = match top_path.syntax().parent().and_then(ast::UseTree::cast) {
|
||||||
Some(tree) => tree.syntax().range().end(),
|
Some(tree) => tree.syntax().text_range().end(),
|
||||||
None => top_path.syntax().range().end(),
|
None => top_path.syntax().text_range().end(),
|
||||||
};
|
};
|
||||||
|
|
||||||
ctx.add_action(AssistId("split_import"), "split import", |edit| {
|
ctx.add_action(AssistId("split_import"), "split import", |edit| {
|
||||||
edit.target(colon_colon.range());
|
edit.target(colon_colon.text_range());
|
||||||
edit.insert(l_curly, "{");
|
edit.insert(l_curly, "{");
|
||||||
edit.insert(r_curly, "}");
|
edit.insert(r_curly, "}");
|
||||||
edit.set_cursor(l_curly + TextUnit::of_str("{"));
|
edit.set_cursor(l_curly + TextUnit::of_str("{"));
|
||||||
|
@ -70,7 +70,7 @@ pub fn run(verbose: bool, memory_usage: bool, path: &Path, only: Option<&str>) -
|
|||||||
let src = f.source(db);
|
let src = f.source(db);
|
||||||
let original_file = src.file_id.original_file(db);
|
let original_file = src.file_id.original_file(db);
|
||||||
let path = db.file_relative_path(original_file);
|
let path = db.file_relative_path(original_file);
|
||||||
let syntax_range = src.ast.syntax().range();
|
let syntax_range = src.ast.syntax().text_range();
|
||||||
write!(msg, " ({:?} {})", path, syntax_range).unwrap();
|
write!(msg, " ({:?} {})", path, syntax_range).unwrap();
|
||||||
}
|
}
|
||||||
bar.set_message(&msg);
|
bar.set_message(&msg);
|
||||||
|
@ -55,7 +55,7 @@ fn main() -> Result<()> {
|
|||||||
let _p = profile("parsing");
|
let _p = profile("parsing");
|
||||||
let file = file()?;
|
let file = file()?;
|
||||||
if !matches.is_present("no-dump") {
|
if !matches.is_present("no-dump") {
|
||||||
println!("{}", file.syntax().debug_dump());
|
println!("{:#?}", file.syntax());
|
||||||
}
|
}
|
||||||
std::mem::forget(file);
|
std::mem::forget(file);
|
||||||
}
|
}
|
||||||
|
@ -843,7 +843,7 @@ where
|
|||||||
let file_id = call_id.as_file(MacroFileKind::Expr);
|
let file_id = call_id.as_file(MacroFileKind::Expr);
|
||||||
if let Some(node) = self.db.parse_or_expand(file_id) {
|
if let Some(node) = self.db.parse_or_expand(file_id) {
|
||||||
if let Some(expr) = ast::Expr::cast(node) {
|
if let Some(expr) = ast::Expr::cast(node) {
|
||||||
log::debug!("macro expansion {}", expr.syntax().debug_dump());
|
log::debug!("macro expansion {:#?}", expr.syntax());
|
||||||
let old_file_id =
|
let old_file_id =
|
||||||
std::mem::replace(&mut self.current_file_id, file_id);
|
std::mem::replace(&mut self.current_file_id, file_id);
|
||||||
let id = self.collect_expr(expr);
|
let id = self.collect_expr(expr);
|
||||||
|
@ -296,7 +296,7 @@ mod tests {
|
|||||||
let local_name_entry = analyzer.resolve_local_name(&name_ref).unwrap();
|
let local_name_entry = analyzer.resolve_local_name(&name_ref).unwrap();
|
||||||
let local_name =
|
let local_name =
|
||||||
local_name_entry.ptr().either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr());
|
local_name_entry.ptr().either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr());
|
||||||
assert_eq!(local_name.range(), expected_name.syntax().range());
|
assert_eq!(local_name.range(), expected_name.syntax().text_range());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -361,7 +361,7 @@ impl SourceAnalyzer {
|
|||||||
})
|
})
|
||||||
.map(|name_ref| ReferenceDescriptor {
|
.map(|name_ref| ReferenceDescriptor {
|
||||||
name: name_ref.text().to_string(),
|
name: name_ref.text().to_string(),
|
||||||
range: name_ref.syntax().range(),
|
range: name_ref.syntax().text_range(),
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
@ -3127,7 +3127,7 @@ fn infer(content: &str) -> String {
|
|||||||
for (syntax_ptr, ty) in &types {
|
for (syntax_ptr, ty) in &types {
|
||||||
let node = syntax_ptr.to_node(source_file.syntax());
|
let node = syntax_ptr.to_node(source_file.syntax());
|
||||||
let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) {
|
let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) {
|
||||||
(self_param.self_kw_token().range(), "self".to_string())
|
(self_param.self_kw_token().text_range(), "self".to_string())
|
||||||
} else {
|
} else {
|
||||||
(syntax_ptr.range(), node.text().to_string().replace("\n", " "))
|
(syntax_ptr.range(), node.text().to_string().replace("\n", " "))
|
||||||
};
|
};
|
||||||
|
@ -47,7 +47,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
|
|||||||
// Number of arguments specified at the call site
|
// Number of arguments specified at the call site
|
||||||
let num_args_at_callsite = arg_list.args().count();
|
let num_args_at_callsite = arg_list.args().count();
|
||||||
|
|
||||||
let arg_list_range = arg_list.syntax().range();
|
let arg_list_range = arg_list.syntax().text_range();
|
||||||
if !arg_list_range.contains_inclusive(position.offset) {
|
if !arg_list_range.contains_inclusive(position.offset) {
|
||||||
tested_by!(call_info_bad_offset);
|
tested_by!(call_info_bad_offset);
|
||||||
return None;
|
return None;
|
||||||
@ -57,7 +57,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
|
|||||||
num_args_at_callsite,
|
num_args_at_callsite,
|
||||||
arg_list
|
arg_list
|
||||||
.args()
|
.args()
|
||||||
.take_while(|arg| arg.syntax().range().end() < position.offset)
|
.take_while(|arg| arg.syntax().text_range().end() < position.offset)
|
||||||
.count(),
|
.count(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ fn is_in_loop_body(leaf: &SyntaxToken) -> bool {
|
|||||||
.visit::<ast::LoopExpr, _>(|it| it.loop_body())
|
.visit::<ast::LoopExpr, _>(|it| it.loop_body())
|
||||||
.accept(&node);
|
.accept(&node);
|
||||||
if let Some(Some(body)) = loop_body {
|
if let Some(Some(body)) = loop_body {
|
||||||
if leaf.range().is_subrange(&body.syntax().range()) {
|
if leaf.text_range().is_subrange(&body.syntax().text_range()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
|
|||||||
if Some(module) == ctx.module {
|
if Some(module) == ctx.module {
|
||||||
if let Some(import) = res.import {
|
if let Some(import) = res.import {
|
||||||
if let Either::A(use_tree) = module.import_source(ctx.db, import) {
|
if let Either::A(use_tree) = module.import_source(ctx.db, import) {
|
||||||
if use_tree.syntax().range().contains_inclusive(ctx.offset) {
|
if use_tree.syntax().text_range().contains_inclusive(ctx.offset) {
|
||||||
// for `use self::foo<|>`, don't suggest `foo` as a completion
|
// for `use self::foo<|>`, don't suggest `foo` as a completion
|
||||||
tested_by!(dont_complete_current_use);
|
tested_by!(dont_complete_current_use);
|
||||||
continue;
|
continue;
|
||||||
|
@ -12,7 +12,7 @@ use ra_text_edit::TextEditBuilder;
|
|||||||
fn postfix_snippet(ctx: &CompletionContext, label: &str, detail: &str, snippet: &str) -> Builder {
|
fn postfix_snippet(ctx: &CompletionContext, label: &str, detail: &str, snippet: &str) -> Builder {
|
||||||
let edit = {
|
let edit = {
|
||||||
let receiver_range =
|
let receiver_range =
|
||||||
ctx.dot_receiver.as_ref().expect("no receiver available").syntax().range();
|
ctx.dot_receiver.as_ref().expect("no receiver available").syntax().text_range();
|
||||||
let delete_range = TextRange::from_to(receiver_range.start(), ctx.source_range().end());
|
let delete_range = TextRange::from_to(receiver_range.start(), ctx.source_range().end());
|
||||||
let mut builder = TextEditBuilder::default();
|
let mut builder = TextEditBuilder::default();
|
||||||
builder.replace(delete_range, snippet.to_string());
|
builder.replace(delete_range, snippet.to_string());
|
||||||
|
@ -78,7 +78,7 @@ impl<'a> CompletionContext<'a> {
|
|||||||
pub(crate) fn source_range(&self) -> TextRange {
|
pub(crate) fn source_range(&self) -> TextRange {
|
||||||
match self.token.kind() {
|
match self.token.kind() {
|
||||||
// workaroud when completion is triggered by trigger characters.
|
// workaroud when completion is triggered by trigger characters.
|
||||||
IDENT => self.token.range(),
|
IDENT => self.token.text_range(),
|
||||||
_ => TextRange::offset_len(self.offset, 0.into()),
|
_ => TextRange::offset_len(self.offset, 0.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,13 +123,17 @@ impl<'a> CompletionContext<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn classify_name_ref(&mut self, original_file: SourceFile, name_ref: ast::NameRef) {
|
fn classify_name_ref(&mut self, original_file: SourceFile, name_ref: ast::NameRef) {
|
||||||
let name_range = name_ref.syntax().range();
|
let name_range = name_ref.syntax().text_range();
|
||||||
if name_ref.syntax().parent().and_then(ast::NamedField::cast).is_some() {
|
if name_ref.syntax().parent().and_then(ast::NamedField::cast).is_some() {
|
||||||
self.struct_lit_syntax = find_node_at_offset(original_file.syntax(), self.offset);
|
self.struct_lit_syntax = find_node_at_offset(original_file.syntax(), self.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
let top_node =
|
let top_node = name_ref
|
||||||
name_ref.syntax().ancestors().take_while(|it| it.range() == name_range).last().unwrap();
|
.syntax()
|
||||||
|
.ancestors()
|
||||||
|
.take_while(|it| it.text_range() == name_range)
|
||||||
|
.last()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
match top_node.parent().map(|it| it.kind()) {
|
match top_node.parent().map(|it| it.kind()) {
|
||||||
Some(SOURCE_FILE) | Some(ITEM_LIST) => {
|
Some(SOURCE_FILE) | Some(ITEM_LIST) => {
|
||||||
@ -180,23 +184,27 @@ impl<'a> CompletionContext<'a> {
|
|||||||
.ancestors()
|
.ancestors()
|
||||||
.find_map(|node| {
|
.find_map(|node| {
|
||||||
if let Some(stmt) = ast::ExprStmt::cast(node.clone()) {
|
if let Some(stmt) = ast::ExprStmt::cast(node.clone()) {
|
||||||
return Some(stmt.syntax().range() == name_ref.syntax().range());
|
return Some(
|
||||||
|
stmt.syntax().text_range() == name_ref.syntax().text_range(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if let Some(block) = ast::Block::cast(node) {
|
if let Some(block) = ast::Block::cast(node) {
|
||||||
return Some(
|
return Some(
|
||||||
block.expr().map(|e| e.syntax().range())
|
block.expr().map(|e| e.syntax().text_range())
|
||||||
== Some(name_ref.syntax().range()),
|
== Some(name_ref.syntax().text_range()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
})
|
})
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
if let Some(off) = name_ref.syntax().range().start().checked_sub(2.into()) {
|
if let Some(off) = name_ref.syntax().text_range().start().checked_sub(2.into()) {
|
||||||
if let Some(if_expr) =
|
if let Some(if_expr) =
|
||||||
find_node_at_offset::<ast::IfExpr>(original_file.syntax(), off)
|
find_node_at_offset::<ast::IfExpr>(original_file.syntax(), off)
|
||||||
{
|
{
|
||||||
if if_expr.syntax().range().end() < name_ref.syntax().range().start() {
|
if if_expr.syntax().text_range().end()
|
||||||
|
< name_ref.syntax().text_range().start()
|
||||||
|
{
|
||||||
self.after_if = true;
|
self.after_if = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -208,14 +216,14 @@ impl<'a> CompletionContext<'a> {
|
|||||||
// ident, so it should have the same range in the non-modified file
|
// ident, so it should have the same range in the non-modified file
|
||||||
self.dot_receiver = field_expr
|
self.dot_receiver = field_expr
|
||||||
.expr()
|
.expr()
|
||||||
.map(|e| e.syntax().range())
|
.map(|e| e.syntax().text_range())
|
||||||
.and_then(|r| find_node_with_range(original_file.syntax(), r));
|
.and_then(|r| find_node_with_range(original_file.syntax(), r));
|
||||||
}
|
}
|
||||||
if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent) {
|
if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent) {
|
||||||
// As above
|
// As above
|
||||||
self.dot_receiver = method_call_expr
|
self.dot_receiver = method_call_expr
|
||||||
.expr()
|
.expr()
|
||||||
.map(|e| e.syntax().range())
|
.map(|e| e.syntax().text_range())
|
||||||
.and_then(|r| find_node_with_range(original_file.syntax(), r));
|
.and_then(|r| find_node_with_range(original_file.syntax(), r));
|
||||||
self.is_call = true;
|
self.is_call = true;
|
||||||
}
|
}
|
||||||
@ -229,6 +237,6 @@ fn find_node_with_range<N: AstNode>(syntax: &SyntaxNode, range: TextRange) -> Op
|
|||||||
fn is_node<N: AstNode>(node: &SyntaxNode) -> bool {
|
fn is_node<N: AstNode>(node: &SyntaxNode) -> bool {
|
||||||
match node.ancestors().filter_map(N::cast).next() {
|
match node.ancestors().filter_map(N::cast).next() {
|
||||||
None => false,
|
None => false,
|
||||||
Some(n) => n.syntax().range() == node.range(),
|
Some(n) => n.syntax().text_range() == node.text_range(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ fn check_unnecessary_braces_in_use_statement(
|
|||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
let use_tree_list = ast::UseTreeList::cast(node.clone())?;
|
let use_tree_list = ast::UseTreeList::cast(node.clone())?;
|
||||||
if let Some((single_use_tree,)) = use_tree_list.use_trees().collect_tuple() {
|
if let Some((single_use_tree,)) = use_tree_list.use_trees().collect_tuple() {
|
||||||
let range = use_tree_list.syntax().range();
|
let range = use_tree_list.syntax().text_range();
|
||||||
let edit =
|
let edit =
|
||||||
text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(&single_use_tree)
|
text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(&single_use_tree)
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
@ -126,8 +126,8 @@ fn text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(
|
|||||||
) -> Option<TextEdit> {
|
) -> Option<TextEdit> {
|
||||||
let use_tree_list_node = single_use_tree.syntax().parent()?;
|
let use_tree_list_node = single_use_tree.syntax().parent()?;
|
||||||
if single_use_tree.path()?.segment()?.syntax().first_child_or_token()?.kind() == T![self] {
|
if single_use_tree.path()?.segment()?.syntax().first_child_or_token()?.kind() == T![self] {
|
||||||
let start = use_tree_list_node.prev_sibling_or_token()?.range().start();
|
let start = use_tree_list_node.prev_sibling_or_token()?.text_range().start();
|
||||||
let end = use_tree_list_node.range().end();
|
let end = use_tree_list_node.text_range().end();
|
||||||
let range = TextRange::from_to(start, end);
|
let range = TextRange::from_to(start, end);
|
||||||
let mut edit_builder = TextEditBuilder::default();
|
let mut edit_builder = TextEditBuilder::default();
|
||||||
edit_builder.delete(range);
|
edit_builder.delete(range);
|
||||||
@ -149,12 +149,12 @@ fn check_struct_shorthand_initialization(
|
|||||||
let field_expr = expr.syntax().text().to_string();
|
let field_expr = expr.syntax().text().to_string();
|
||||||
if field_name == field_expr {
|
if field_name == field_expr {
|
||||||
let mut edit_builder = TextEditBuilder::default();
|
let mut edit_builder = TextEditBuilder::default();
|
||||||
edit_builder.delete(named_field.syntax().range());
|
edit_builder.delete(named_field.syntax().text_range());
|
||||||
edit_builder.insert(named_field.syntax().range().start(), field_name);
|
edit_builder.insert(named_field.syntax().text_range().start(), field_name);
|
||||||
let edit = edit_builder.finish();
|
let edit = edit_builder.finish();
|
||||||
|
|
||||||
acc.push(Diagnostic {
|
acc.push(Diagnostic {
|
||||||
range: named_field.syntax().range(),
|
range: named_field.syntax().text_range(),
|
||||||
message: "Shorthand struct initialization".to_string(),
|
message: "Shorthand struct initialization".to_string(),
|
||||||
severity: Severity::WeakWarning,
|
severity: Severity::WeakWarning,
|
||||||
fix: Some(SourceChange::source_file_edit(
|
fix: Some(SourceChange::source_file_edit(
|
||||||
|
@ -233,7 +233,7 @@ impl NavigationTarget {
|
|||||||
|
|
||||||
pub(crate) fn from_macro_def(db: &RootDatabase, macro_call: hir::MacroDef) -> NavigationTarget {
|
pub(crate) fn from_macro_def(db: &RootDatabase, macro_call: hir::MacroDef) -> NavigationTarget {
|
||||||
let src = macro_call.source(db);
|
let src = macro_call.source(db);
|
||||||
log::debug!("nav target {}", src.ast.syntax().debug_dump());
|
log::debug!("nav target {:#?}", src.ast.syntax());
|
||||||
NavigationTarget::from_named(
|
NavigationTarget::from_named(
|
||||||
src.file_id.original_file(db),
|
src.file_id.original_file(db),
|
||||||
&src.ast,
|
&src.ast,
|
||||||
@ -275,7 +275,7 @@ impl NavigationTarget {
|
|||||||
) -> NavigationTarget {
|
) -> NavigationTarget {
|
||||||
//FIXME: use `_` instead of empty string
|
//FIXME: use `_` instead of empty string
|
||||||
let name = node.name().map(|it| it.text().clone()).unwrap_or_default();
|
let name = node.name().map(|it| it.text().clone()).unwrap_or_default();
|
||||||
let focus_range = node.name().map(|it| it.syntax().range());
|
let focus_range = node.name().map(|it| it.syntax().text_range());
|
||||||
NavigationTarget::from_syntax(file_id, name, focus_range, node.syntax(), docs, description)
|
NavigationTarget::from_syntax(file_id, name, focus_range, node.syntax(), docs, description)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,7 +291,7 @@ impl NavigationTarget {
|
|||||||
file_id,
|
file_id,
|
||||||
name,
|
name,
|
||||||
kind: node.kind(),
|
kind: node.kind(),
|
||||||
full_range: node.range(),
|
full_range: node.text_range(),
|
||||||
focus_range,
|
focus_range,
|
||||||
// ptr: Some(LocalSyntaxPtr::new(node)),
|
// ptr: Some(LocalSyntaxPtr::new(node)),
|
||||||
container_name: None,
|
container_name: None,
|
||||||
|
@ -73,8 +73,8 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
|
|||||||
Some(StructureNode {
|
Some(StructureNode {
|
||||||
parent: None,
|
parent: None,
|
||||||
label: name.text().to_string(),
|
label: name.text().to_string(),
|
||||||
navigation_range: name.syntax().range(),
|
navigation_range: name.syntax().text_range(),
|
||||||
node_range: node.syntax().range(),
|
node_range: node.syntax().text_range(),
|
||||||
kind: node.syntax().kind(),
|
kind: node.syntax().kind(),
|
||||||
detail,
|
detail,
|
||||||
deprecated: node.attrs().filter_map(|x| x.as_named()).any(|x| x == "deprecated"),
|
deprecated: node.attrs().filter_map(|x| x.as_named()).any(|x| x == "deprecated"),
|
||||||
@ -140,8 +140,8 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
|
|||||||
let node = StructureNode {
|
let node = StructureNode {
|
||||||
parent: None,
|
parent: None,
|
||||||
label,
|
label,
|
||||||
navigation_range: target_type.syntax().range(),
|
navigation_range: target_type.syntax().text_range(),
|
||||||
node_range: im.syntax().range(),
|
node_range: im.syntax().text_range(),
|
||||||
kind: im.syntax().kind(),
|
kind: im.syntax().kind(),
|
||||||
detail: None,
|
detail: None,
|
||||||
deprecated: false,
|
deprecated: false,
|
||||||
|
@ -42,19 +42,20 @@ fn try_extend_selection(root: &SyntaxNode, range: TextRange) -> Option<TextRange
|
|||||||
TokenAtOffset::None => return None,
|
TokenAtOffset::None => return None,
|
||||||
TokenAtOffset::Single(l) => {
|
TokenAtOffset::Single(l) => {
|
||||||
if string_kinds.contains(&l.kind()) {
|
if string_kinds.contains(&l.kind()) {
|
||||||
extend_single_word_in_comment_or_string(&l, offset).unwrap_or_else(|| l.range())
|
extend_single_word_in_comment_or_string(&l, offset)
|
||||||
|
.unwrap_or_else(|| l.text_range())
|
||||||
} else {
|
} else {
|
||||||
l.range()
|
l.text_range()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TokenAtOffset::Between(l, r) => pick_best(l, r).range(),
|
TokenAtOffset::Between(l, r) => pick_best(l, r).text_range(),
|
||||||
};
|
};
|
||||||
return Some(leaf_range);
|
return Some(leaf_range);
|
||||||
};
|
};
|
||||||
let node = match find_covering_element(root, range) {
|
let node = match find_covering_element(root, range) {
|
||||||
SyntaxElement::Token(token) => {
|
SyntaxElement::Token(token) => {
|
||||||
if token.range() != range {
|
if token.text_range() != range {
|
||||||
return Some(token.range());
|
return Some(token.text_range());
|
||||||
}
|
}
|
||||||
if let Some(comment) = ast::Comment::cast(token.clone()) {
|
if let Some(comment) = ast::Comment::cast(token.clone()) {
|
||||||
if let Some(range) = extend_comments(comment) {
|
if let Some(range) = extend_comments(comment) {
|
||||||
@ -65,12 +66,12 @@ fn try_extend_selection(root: &SyntaxNode, range: TextRange) -> Option<TextRange
|
|||||||
}
|
}
|
||||||
SyntaxElement::Node(node) => node,
|
SyntaxElement::Node(node) => node,
|
||||||
};
|
};
|
||||||
if node.range() != range {
|
if node.text_range() != range {
|
||||||
return Some(node.range());
|
return Some(node.text_range());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Using shallowest node with same range allows us to traverse siblings.
|
// Using shallowest node with same range allows us to traverse siblings.
|
||||||
let node = node.ancestors().take_while(|n| n.range() == node.range()).last().unwrap();
|
let node = node.ancestors().take_while(|n| n.text_range() == node.text_range()).last().unwrap();
|
||||||
|
|
||||||
if node.parent().map(|n| list_kinds.contains(&n.kind())) == Some(true) {
|
if node.parent().map(|n| list_kinds.contains(&n.kind())) == Some(true) {
|
||||||
if let Some(range) = extend_list_item(&node) {
|
if let Some(range) = extend_list_item(&node) {
|
||||||
@ -78,7 +79,7 @@ fn try_extend_selection(root: &SyntaxNode, range: TextRange) -> Option<TextRange
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node.parent().map(|it| it.range())
|
node.parent().map(|it| it.text_range())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extend_single_word_in_comment_or_string(
|
fn extend_single_word_in_comment_or_string(
|
||||||
@ -86,7 +87,7 @@ fn extend_single_word_in_comment_or_string(
|
|||||||
offset: TextUnit,
|
offset: TextUnit,
|
||||||
) -> Option<TextRange> {
|
) -> Option<TextRange> {
|
||||||
let text: &str = leaf.text();
|
let text: &str = leaf.text();
|
||||||
let cursor_position: u32 = (offset - leaf.range().start()).into();
|
let cursor_position: u32 = (offset - leaf.text_range().start()).into();
|
||||||
|
|
||||||
let (before, after) = text.split_at(cursor_position as usize);
|
let (before, after) = text.split_at(cursor_position as usize);
|
||||||
|
|
||||||
@ -104,31 +105,31 @@ fn extend_single_word_in_comment_or_string(
|
|||||||
if range.is_empty() {
|
if range.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(range + leaf.range().start())
|
Some(range + leaf.text_range().start())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extend_ws(root: &SyntaxNode, ws: SyntaxToken, offset: TextUnit) -> TextRange {
|
fn extend_ws(root: &SyntaxNode, ws: SyntaxToken, offset: TextUnit) -> TextRange {
|
||||||
let ws_text = ws.text();
|
let ws_text = ws.text();
|
||||||
let suffix = TextRange::from_to(offset, ws.range().end()) - ws.range().start();
|
let suffix = TextRange::from_to(offset, ws.text_range().end()) - ws.text_range().start();
|
||||||
let prefix = TextRange::from_to(ws.range().start(), offset) - ws.range().start();
|
let prefix = TextRange::from_to(ws.text_range().start(), offset) - ws.text_range().start();
|
||||||
let ws_suffix = &ws_text.as_str()[suffix];
|
let ws_suffix = &ws_text.as_str()[suffix];
|
||||||
let ws_prefix = &ws_text.as_str()[prefix];
|
let ws_prefix = &ws_text.as_str()[prefix];
|
||||||
if ws_text.contains('\n') && !ws_suffix.contains('\n') {
|
if ws_text.contains('\n') && !ws_suffix.contains('\n') {
|
||||||
if let Some(node) = ws.next_sibling_or_token() {
|
if let Some(node) = ws.next_sibling_or_token() {
|
||||||
let start = match ws_prefix.rfind('\n') {
|
let start = match ws_prefix.rfind('\n') {
|
||||||
Some(idx) => ws.range().start() + TextUnit::from((idx + 1) as u32),
|
Some(idx) => ws.text_range().start() + TextUnit::from((idx + 1) as u32),
|
||||||
None => node.range().start(),
|
None => node.text_range().start(),
|
||||||
};
|
};
|
||||||
let end = if root.text().char_at(node.range().end()) == Some('\n') {
|
let end = if root.text().char_at(node.text_range().end()) == Some('\n') {
|
||||||
node.range().end() + TextUnit::of_char('\n')
|
node.text_range().end() + TextUnit::of_char('\n')
|
||||||
} else {
|
} else {
|
||||||
node.range().end()
|
node.text_range().end()
|
||||||
};
|
};
|
||||||
return TextRange::from_to(start, end);
|
return TextRange::from_to(start, end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ws.range()
|
ws.text_range()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pick_best<'a>(l: SyntaxToken, r: SyntaxToken) -> SyntaxToken {
|
fn pick_best<'a>(l: SyntaxToken, r: SyntaxToken) -> SyntaxToken {
|
||||||
@ -161,7 +162,7 @@ fn extend_list_item(node: &SyntaxNode) -> Option<TextRange> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(comma_node) = nearby_comma(node, Direction::Prev) {
|
if let Some(comma_node) = nearby_comma(node, Direction::Prev) {
|
||||||
return Some(TextRange::from_to(comma_node.range().start(), node.range().end()));
|
return Some(TextRange::from_to(comma_node.text_range().start(), node.text_range().end()));
|
||||||
}
|
}
|
||||||
if let Some(comma_node) = nearby_comma(node, Direction::Next) {
|
if let Some(comma_node) = nearby_comma(node, Direction::Next) {
|
||||||
// Include any following whitespace when comma if after list item.
|
// Include any following whitespace when comma if after list item.
|
||||||
@ -171,7 +172,7 @@ fn extend_list_item(node: &SyntaxNode) -> Option<TextRange> {
|
|||||||
.filter(|node| is_single_line_ws(node))
|
.filter(|node| is_single_line_ws(node))
|
||||||
.unwrap_or(comma_node);
|
.unwrap_or(comma_node);
|
||||||
|
|
||||||
return Some(TextRange::from_to(node.range().start(), final_node.range().end()));
|
return Some(TextRange::from_to(node.text_range().start(), final_node.text_range().end()));
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
@ -181,7 +182,10 @@ fn extend_comments(comment: ast::Comment) -> Option<TextRange> {
|
|||||||
let prev = adj_comments(&comment, Direction::Prev);
|
let prev = adj_comments(&comment, Direction::Prev);
|
||||||
let next = adj_comments(&comment, Direction::Next);
|
let next = adj_comments(&comment, Direction::Next);
|
||||||
if prev != next {
|
if prev != next {
|
||||||
Some(TextRange::from_to(prev.syntax().range().start(), next.syntax().range().end()))
|
Some(TextRange::from_to(
|
||||||
|
prev.syntax().text_range().start(),
|
||||||
|
next.syntax().text_range().end(),
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
|
|||||||
SyntaxElement::Token(token) => token.text().contains('\n'),
|
SyntaxElement::Token(token) => token.text().contains('\n'),
|
||||||
};
|
};
|
||||||
if is_multiline {
|
if is_multiline {
|
||||||
res.push(Fold { range: element.range(), kind });
|
res.push(Fold { range: element.text_range(), kind });
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,7 +132,7 @@ fn contiguous_range_for_group_unless(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if first != &last {
|
if first != &last {
|
||||||
Some(TextRange::from_to(first.range().start(), last.range().end()))
|
Some(TextRange::from_to(first.text_range().start(), last.text_range().end()))
|
||||||
} else {
|
} else {
|
||||||
// The group consists of only one element, therefore it cannot be folded
|
// The group consists of only one element, therefore it cannot be folded
|
||||||
None
|
None
|
||||||
@ -178,7 +178,10 @@ fn contiguous_range_for_comment(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if first != last {
|
if first != last {
|
||||||
Some(TextRange::from_to(first.syntax().range().start(), last.syntax().range().end()))
|
Some(TextRange::from_to(
|
||||||
|
first.syntax().text_range().start(),
|
||||||
|
last.syntax().text_range().end(),
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
// The group consists of only one element, therefore it cannot be folded
|
// The group consists of only one element, therefore it cannot be folded
|
||||||
None
|
None
|
||||||
|
@ -23,11 +23,11 @@ pub(crate) fn goto_definition(
|
|||||||
let syntax = parse.tree().syntax().clone();
|
let syntax = parse.tree().syntax().clone();
|
||||||
if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&syntax, position.offset) {
|
if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&syntax, position.offset) {
|
||||||
let navs = reference_definition(db, position.file_id, &name_ref).to_vec();
|
let navs = reference_definition(db, position.file_id, &name_ref).to_vec();
|
||||||
return Some(RangeInfo::new(name_ref.syntax().range(), navs.to_vec()));
|
return Some(RangeInfo::new(name_ref.syntax().text_range(), navs.to_vec()));
|
||||||
}
|
}
|
||||||
if let Some(name) = find_node_at_offset::<ast::Name>(&syntax, position.offset) {
|
if let Some(name) = find_node_at_offset::<ast::Name>(&syntax, position.offset) {
|
||||||
let navs = name_definition(db, position.file_id, &name)?;
|
let navs = name_definition(db, position.file_id, &name)?;
|
||||||
return Some(RangeInfo::new(name.syntax().range(), navs));
|
return Some(RangeInfo::new(name.syntax().text_range(), navs));
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ pub(crate) fn goto_type_definition(
|
|||||||
let adt_def = analyzer.autoderef(db, ty).find_map(|ty| ty.as_adt().map(|adt| adt.0))?;
|
let adt_def = analyzer.autoderef(db, ty).find_map(|ty| ty.as_adt().map(|adt| adt.0))?;
|
||||||
|
|
||||||
let nav = NavigationTarget::from_adt_def(db, adt_def);
|
let nav = NavigationTarget::from_adt_def(db, adt_def);
|
||||||
Some(RangeInfo::new(node.range(), vec![nav]))
|
Some(RangeInfo::new(node.text_range(), vec![nav]))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -172,7 +172,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !res.is_empty() {
|
if !res.is_empty() {
|
||||||
range = Some(name_ref.syntax().range())
|
range = Some(name_ref.syntax().text_range())
|
||||||
}
|
}
|
||||||
} else if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), position.offset) {
|
} else if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), position.offset) {
|
||||||
if let Some(parent) = name.syntax().parent() {
|
if let Some(parent) = name.syntax().parent() {
|
||||||
@ -210,7 +210,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !res.is_empty() && range.is_none() {
|
if !res.is_empty() && range.is_none() {
|
||||||
range = Some(name.syntax().range());
|
range = Some(name.syntax().text_range());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,9 +218,9 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
|
|||||||
let node = ancestors_at_offset(file.syntax(), position.offset).find(|n| {
|
let node = ancestors_at_offset(file.syntax(), position.offset).find(|n| {
|
||||||
ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some()
|
ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some()
|
||||||
})?;
|
})?;
|
||||||
let frange = FileRange { file_id: position.file_id, range: node.range() };
|
let frange = FileRange { file_id: position.file_id, range: node.text_range() };
|
||||||
res.extend(type_of(db, frange).map(rust_code_markup));
|
res.extend(type_of(db, frange).map(rust_code_markup));
|
||||||
range = Some(node.range());
|
range = Some(node.text_range());
|
||||||
}
|
}
|
||||||
|
|
||||||
let range = range?;
|
let range = range?;
|
||||||
@ -246,7 +246,7 @@ pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option<String> {
|
|||||||
// if we picked identifier, expand to pattern/expression
|
// if we picked identifier, expand to pattern/expression
|
||||||
let node = leaf_node
|
let node = leaf_node
|
||||||
.ancestors()
|
.ancestors()
|
||||||
.take_while(|it| it.range() == leaf_node.range())
|
.take_while(|it| it.text_range() == leaf_node.text_range())
|
||||||
.find(|it| ast::Expr::cast(it.clone()).is_some() || ast::Pat::cast(it.clone()).is_some())?;
|
.find(|it| ast::Expr::cast(it.clone()).is_some() || ast::Pat::cast(it.clone()).is_some())?;
|
||||||
let analyzer = hir::SourceAnalyzer::new(db, frange.file_id, &node, None);
|
let analyzer = hir::SourceAnalyzer::new(db, frange.file_id, &node, None);
|
||||||
let ty = if let Some(ty) = ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e))
|
let ty = if let Some(ty) = ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e))
|
||||||
|
@ -15,12 +15,12 @@ pub(crate) fn goto_implementation(
|
|||||||
|
|
||||||
if let Some(nominal_def) = find_node_at_offset::<ast::NominalDef>(&syntax, position.offset) {
|
if let Some(nominal_def) = find_node_at_offset::<ast::NominalDef>(&syntax, position.offset) {
|
||||||
return Some(RangeInfo::new(
|
return Some(RangeInfo::new(
|
||||||
nominal_def.syntax().range(),
|
nominal_def.syntax().text_range(),
|
||||||
impls_for_def(db, &nominal_def, module)?,
|
impls_for_def(db, &nominal_def, module)?,
|
||||||
));
|
));
|
||||||
} else if let Some(trait_def) = find_node_at_offset::<ast::TraitDef>(&syntax, position.offset) {
|
} else if let Some(trait_def) = find_node_at_offset::<ast::TraitDef>(&syntax, position.offset) {
|
||||||
return Some(RangeInfo::new(
|
return Some(RangeInfo::new(
|
||||||
trait_def.syntax().range(),
|
trait_def.syntax().text_range(),
|
||||||
impls_for_trait(db, &trait_def, module)?,
|
impls_for_trait(db, &trait_def, module)?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -28,14 +28,14 @@ pub fn join_lines(file: &SourceFile, range: TextRange) -> TextEdit {
|
|||||||
};
|
};
|
||||||
let mut edit = TextEditBuilder::default();
|
let mut edit = TextEditBuilder::default();
|
||||||
for token in node.descendants_with_tokens().filter_map(|it| it.into_token()) {
|
for token in node.descendants_with_tokens().filter_map(|it| it.into_token()) {
|
||||||
let range = match range.intersection(&token.range()) {
|
let range = match range.intersection(&token.text_range()) {
|
||||||
Some(range) => range,
|
Some(range) => range,
|
||||||
None => continue,
|
None => continue,
|
||||||
} - token.range().start();
|
} - token.text_range().start();
|
||||||
let text = token.text();
|
let text = token.text();
|
||||||
for (pos, _) in text[range].bytes().enumerate().filter(|&(_, b)| b == b'\n') {
|
for (pos, _) in text[range].bytes().enumerate().filter(|&(_, b)| b == b'\n') {
|
||||||
let pos: TextUnit = (pos as u32).into();
|
let pos: TextUnit = (pos as u32).into();
|
||||||
let off = token.range().start() + range.start() + pos;
|
let off = token.text_range().start() + range.start() + pos;
|
||||||
if !edit.invalidates_offset(off) {
|
if !edit.invalidates_offset(off) {
|
||||||
remove_newline(&mut edit, &token, off);
|
remove_newline(&mut edit, &token, off);
|
||||||
}
|
}
|
||||||
@ -49,7 +49,7 @@ fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextU
|
|||||||
if token.kind() != WHITESPACE || token.text().bytes().filter(|&b| b == b'\n').count() != 1 {
|
if token.kind() != WHITESPACE || token.text().bytes().filter(|&b| b == b'\n').count() != 1 {
|
||||||
// The node is either the first or the last in the file
|
// The node is either the first or the last in the file
|
||||||
let suff = &token.text()[TextRange::from_to(
|
let suff = &token.text()[TextRange::from_to(
|
||||||
offset - token.range().start() + TextUnit::of_char('\n'),
|
offset - token.text_range().start() + TextUnit::of_char('\n'),
|
||||||
TextUnit::of_str(token.text()),
|
TextUnit::of_str(token.text()),
|
||||||
)];
|
)];
|
||||||
let spaces = suff.bytes().take_while(|&b| b == b' ').count();
|
let spaces = suff.bytes().take_while(|&b| b == b' ').count();
|
||||||
@ -86,7 +86,7 @@ fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextU
|
|||||||
let next = token.next_sibling_or_token().unwrap();
|
let next = token.next_sibling_or_token().unwrap();
|
||||||
if is_trailing_comma(prev.kind(), next.kind()) {
|
if is_trailing_comma(prev.kind(), next.kind()) {
|
||||||
// Removes: trailing comma, newline (incl. surrounding whitespace)
|
// Removes: trailing comma, newline (incl. surrounding whitespace)
|
||||||
edit.delete(TextRange::from_to(prev.range().start(), token.range().end()));
|
edit.delete(TextRange::from_to(prev.text_range().start(), token.text_range().end()));
|
||||||
} else if prev.kind() == T![,] && next.kind() == T!['}'] {
|
} else if prev.kind() == T![,] && next.kind() == T!['}'] {
|
||||||
// Removes: comma, newline (incl. surrounding whitespace)
|
// Removes: comma, newline (incl. surrounding whitespace)
|
||||||
let space = if let Some(left) = prev.prev_sibling_or_token() {
|
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
|
|||||||
" "
|
" "
|
||||||
};
|
};
|
||||||
edit.replace(
|
edit.replace(
|
||||||
TextRange::from_to(prev.range().start(), token.range().end()),
|
TextRange::from_to(prev.text_range().start(), token.text_range().end()),
|
||||||
space.to_string(),
|
space.to_string(),
|
||||||
);
|
);
|
||||||
} else if let (Some(_), Some(next)) = (
|
} else if let (Some(_), Some(next)) = (
|
||||||
@ -104,12 +104,12 @@ fn remove_newline(edit: &mut TextEditBuilder, token: &SyntaxToken, offset: TextU
|
|||||||
) {
|
) {
|
||||||
// Removes: newline (incl. surrounding whitespace), start of the next comment
|
// Removes: newline (incl. surrounding whitespace), start of the next comment
|
||||||
edit.delete(TextRange::from_to(
|
edit.delete(TextRange::from_to(
|
||||||
token.range().start(),
|
token.text_range().start(),
|
||||||
next.syntax().range().start() + TextUnit::of_str(next.prefix()),
|
next.syntax().text_range().start() + TextUnit::of_str(next.prefix()),
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
// Remove newline but add a computed amount of whitespace characters
|
// Remove newline but add a computed amount of whitespace characters
|
||||||
edit.replace(token.range(), compute_ws(prev.kind(), next.kind()).to_string());
|
edit.replace(token.text_range(), compute_ws(prev.kind(), next.kind()).to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ fn join_single_expr_block(edit: &mut TextEditBuilder, token: &SyntaxToken) -> Op
|
|||||||
let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?;
|
let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?;
|
||||||
let expr = extract_trivial_expression(&block)?;
|
let expr = extract_trivial_expression(&block)?;
|
||||||
|
|
||||||
let block_range = block_expr.syntax().range();
|
let block_range = block_expr.syntax().text_range();
|
||||||
let mut buf = expr.syntax().text().to_string();
|
let mut buf = expr.syntax().text().to_string();
|
||||||
|
|
||||||
// Match block needs to have a comma after the block
|
// 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
|
|||||||
fn join_single_use_tree(edit: &mut TextEditBuilder, token: &SyntaxToken) -> Option<()> {
|
fn join_single_use_tree(edit: &mut TextEditBuilder, token: &SyntaxToken) -> Option<()> {
|
||||||
let use_tree_list = ast::UseTreeList::cast(token.parent())?;
|
let use_tree_list = ast::UseTreeList::cast(token.parent())?;
|
||||||
let (tree,) = use_tree_list.use_trees().collect_tuple()?;
|
let (tree,) = use_tree_list.use_trees().collect_tuple()?;
|
||||||
edit.replace(use_tree_list.syntax().range(), tree.syntax().text().to_string());
|
edit.replace(use_tree_list.syntax().text_range(), tree.syntax().text().to_string());
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ pub fn matching_brace(file: &SourceFile, offset: TextUnit) -> Option<TextUnit> {
|
|||||||
let parent = brace_node.parent();
|
let parent = brace_node.parent();
|
||||||
let matching_kind = BRACES[brace_idx ^ 1];
|
let matching_kind = BRACES[brace_idx ^ 1];
|
||||||
let matching_node = parent.children_with_tokens().find(|node| node.kind() == matching_kind)?;
|
let matching_node = parent.children_with_tokens().find(|node| node.kind() == matching_kind)?;
|
||||||
Some(matching_node.range().start())
|
Some(matching_node.text_range().start())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -166,7 +166,7 @@ fn rename_mod(
|
|||||||
file_id: position.file_id,
|
file_id: position.file_id,
|
||||||
edit: {
|
edit: {
|
||||||
let mut builder = ra_text_edit::TextEditBuilder::default();
|
let mut builder = ra_text_edit::TextEditBuilder::default();
|
||||||
builder.replace(ast_name.syntax().range(), new_name.into());
|
builder.replace(ast_name.syntax().text_range(), new_name.into());
|
||||||
builder.finish()
|
builder.finish()
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -47,7 +47,7 @@ fn runnable_fn(fn_def: ast::FnDef) -> Option<Runnable> {
|
|||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
Some(Runnable { range: fn_def.syntax().range(), kind })
|
Some(Runnable { range: fn_def.syntax().text_range(), kind })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn runnable_mod(db: &RootDatabase, file_id: FileId, module: ast::Module) -> Option<Runnable> {
|
fn 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
|
|||||||
if !has_test_function {
|
if !has_test_function {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let range = module.syntax().range();
|
let range = module.syntax().text_range();
|
||||||
let module = hir::source_binder::module_from_child_node(db, file_id, module.syntax())?;
|
let module = hir::source_binder::module_from_child_node(db, file_id, module.syntax())?;
|
||||||
|
|
||||||
let path = module.path_to_root(db).into_iter().rev().filter_map(|it| it.name(db)).join("::");
|
let path = module.path_to_root(db).into_iter().rev().filter_map(|it| it.name(db)).join("::");
|
||||||
|
@ -271,7 +271,7 @@ fn source_file_to_file_symbols(source_file: &SourceFile, file_id: FileId) -> Vec
|
|||||||
fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr, TextRange)> {
|
fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr, TextRange)> {
|
||||||
fn decl<N: NameOwner>(node: N) -> Option<(SmolStr, SyntaxNodePtr, TextRange)> {
|
fn decl<N: NameOwner>(node: N) -> Option<(SmolStr, SyntaxNodePtr, TextRange)> {
|
||||||
let name = node.name()?;
|
let name = node.name()?;
|
||||||
let name_range = name.syntax().range();
|
let name_range = name.syntax().text_range();
|
||||||
let name = name.text().clone();
|
let name = name.text().clone();
|
||||||
let ptr = SyntaxNodePtr::new(node.syntax());
|
let ptr = SyntaxNodePtr::new(node.syntax());
|
||||||
|
|
||||||
|
@ -189,11 +189,11 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa
|
|||||||
if let Some(segment) = path.segment() {
|
if let Some(segment) = path.segment() {
|
||||||
if let Some(name_ref) = segment.name_ref() {
|
if let Some(name_ref) = segment.name_ref() {
|
||||||
highlighted.insert(name_ref.syntax().clone().into());
|
highlighted.insert(name_ref.syntax().clone().into());
|
||||||
let range_start = name_ref.syntax().range().start();
|
let range_start = name_ref.syntax().text_range().start();
|
||||||
let mut range_end = name_ref.syntax().range().end();
|
let mut range_end = name_ref.syntax().text_range().end();
|
||||||
for sibling in path.syntax().siblings_with_tokens(Direction::Next) {
|
for sibling in path.syntax().siblings_with_tokens(Direction::Next) {
|
||||||
match sibling.kind() {
|
match sibling.kind() {
|
||||||
T![!] | IDENT => range_end = sibling.range().end(),
|
T![!] | IDENT => range_end = sibling.text_range().end(),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,7 +209,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
res.push(HighlightedRange { range: node.range(), tag, binding_hash })
|
res.push(HighlightedRange { range: node.text_range(), tag, binding_hash })
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
@ -239,9 +239,9 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo
|
|||||||
buf.push_str("<pre><code>");
|
buf.push_str("<pre><code>");
|
||||||
let tokens = parse.tree().syntax().descendants_with_tokens().filter_map(|it| it.into_token());
|
let tokens = parse.tree().syntax().descendants_with_tokens().filter_map(|it| it.into_token());
|
||||||
for token in tokens {
|
for token in tokens {
|
||||||
could_intersect.retain(|it| token.range().start() <= it.range.end());
|
could_intersect.retain(|it| token.text_range().start() <= it.range.end());
|
||||||
while let Some(r) = ranges.get(frontier) {
|
while let Some(r) = ranges.get(frontier) {
|
||||||
if r.range.start() <= token.range().end() {
|
if r.range.start() <= token.text_range().end() {
|
||||||
could_intersect.push(r);
|
could_intersect.push(r);
|
||||||
frontier += 1;
|
frontier += 1;
|
||||||
} else {
|
} else {
|
||||||
@ -251,7 +251,7 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo
|
|||||||
let text = html_escape(&token.text());
|
let text = html_escape(&token.text());
|
||||||
let ranges = could_intersect
|
let ranges = could_intersect
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|it| token.range().is_subrange(&it.range))
|
.filter(|it| token.text_range().is_subrange(&it.range))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
if ranges.is_empty() {
|
if ranges.is_empty() {
|
||||||
buf.push_str(&text);
|
buf.push_str(&text);
|
||||||
|
@ -25,9 +25,9 @@ pub(crate) fn syntax_tree(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
node.debug_dump()
|
format!("{:#?}", node)
|
||||||
} else {
|
} else {
|
||||||
parse.tree().syntax().debug_dump()
|
format!("{:#?}", parse.tree().syntax())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ fn syntax_tree_for_string(token: &SyntaxToken, text_range: TextRange) -> Option<
|
|||||||
|
|
||||||
fn syntax_tree_for_token(node: &SyntaxToken, text_range: TextRange) -> Option<String> {
|
fn syntax_tree_for_token(node: &SyntaxToken, text_range: TextRange) -> Option<String> {
|
||||||
// Range of the full node
|
// Range of the full node
|
||||||
let node_range = node.range();
|
let node_range = node.text_range();
|
||||||
let text = node.text().to_string();
|
let text = node.text().to_string();
|
||||||
|
|
||||||
// We start at some point inside the node
|
// We start at some point inside the node
|
||||||
@ -85,7 +85,7 @@ fn syntax_tree_for_token(node: &SyntaxToken, text_range: TextRange) -> Option<St
|
|||||||
// If the "file" parsed without errors,
|
// If the "file" parsed without errors,
|
||||||
// return its syntax
|
// return its syntax
|
||||||
if parsed.errors().is_empty() {
|
if parsed.errors().is_empty() {
|
||||||
return Some(parsed.tree().syntax().debug_dump());
|
return Some(format!("{:#?}", parsed.tree().syntax()));
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
|
@ -24,7 +24,7 @@ pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<Sour
|
|||||||
|
|
||||||
let prefix = comment.prefix();
|
let prefix = comment.prefix();
|
||||||
if position.offset
|
if position.offset
|
||||||
< comment.syntax().range().start() + TextUnit::of_str(prefix) + TextUnit::from(1)
|
< comment.syntax().text_range().start() + TextUnit::of_str(prefix) + TextUnit::from(1)
|
||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@ -45,7 +45,7 @@ pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<Sour
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn node_indent(file: &SourceFile, token: &SyntaxToken) -> Option<SmolStr> {
|
fn node_indent(file: &SourceFile, token: &SyntaxToken) -> Option<SmolStr> {
|
||||||
let ws = match find_token_at_offset(file.syntax(), token.range().start()) {
|
let ws = match find_token_at_offset(file.syntax(), token.text_range().start()) {
|
||||||
TokenAtOffset::Between(l, r) => {
|
TokenAtOffset::Between(l, r) => {
|
||||||
assert!(r == *token);
|
assert!(r == *token);
|
||||||
l
|
l
|
||||||
@ -71,7 +71,7 @@ pub fn on_eq_typed(file: &SourceFile, eq_offset: TextUnit) -> Option<TextEdit> {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
if let Some(expr) = let_stmt.initializer() {
|
if let Some(expr) = let_stmt.initializer() {
|
||||||
let expr_range = expr.syntax().range();
|
let expr_range = expr.syntax().text_range();
|
||||||
if expr_range.contains(eq_offset) && eq_offset != expr_range.start() {
|
if expr_range.contains(eq_offset) && eq_offset != expr_range.start() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@ -81,7 +81,7 @@ pub fn on_eq_typed(file: &SourceFile, eq_offset: TextUnit) -> Option<TextEdit> {
|
|||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let offset = let_stmt.syntax().range().end();
|
let offset = let_stmt.syntax().text_range().end();
|
||||||
let mut edit = TextEditBuilder::default();
|
let mut edit = TextEditBuilder::default();
|
||||||
edit.insert(offset, ";".to_string());
|
edit.insert(offset, ";".to_string());
|
||||||
Some(edit.finish())
|
Some(edit.finish())
|
||||||
|
@ -19,7 +19,7 @@ pub struct TokenMap {
|
|||||||
pub fn ast_to_token_tree(ast: &ast::TokenTree) -> Option<(tt::Subtree, TokenMap)> {
|
pub fn ast_to_token_tree(ast: &ast::TokenTree) -> Option<(tt::Subtree, TokenMap)> {
|
||||||
let mut token_map = TokenMap::default();
|
let mut token_map = TokenMap::default();
|
||||||
let node = ast.syntax();
|
let node = ast.syntax();
|
||||||
let tt = convert_tt(&mut token_map, node.range().start(), node)?;
|
let tt = convert_tt(&mut token_map, node.text_range().start(), node)?;
|
||||||
Some((tt, token_map))
|
Some((tt, token_map))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ pub fn ast_to_token_tree(ast: &ast::TokenTree) -> Option<(tt::Subtree, TokenMap)
|
|||||||
/// will consume).
|
/// will consume).
|
||||||
pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> Option<(tt::Subtree, TokenMap)> {
|
pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> Option<(tt::Subtree, TokenMap)> {
|
||||||
let mut token_map = TokenMap::default();
|
let mut token_map = TokenMap::default();
|
||||||
let tt = convert_tt(&mut token_map, node.range().start(), node)?;
|
let tt = convert_tt(&mut token_map, node.text_range().start(), node)?;
|
||||||
Some((tt, token_map))
|
Some((tt, token_map))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,7 +229,7 @@ fn convert_tt(
|
|||||||
|| token.kind() == IDENT
|
|| token.kind() == IDENT
|
||||||
|| token.kind() == LIFETIME
|
|| token.kind() == LIFETIME
|
||||||
{
|
{
|
||||||
let relative_range = token.range() - global_offset;
|
let relative_range = token.text_range() - global_offset;
|
||||||
let id = token_map.alloc(relative_range);
|
let id = token_map.alloc(relative_range);
|
||||||
let text = token.text().clone();
|
let text = token.text().clone();
|
||||||
tt::Leaf::from(tt::Ident { text, id }).into()
|
tt::Leaf::from(tt::Ident { text, id }).into()
|
||||||
|
@ -412,7 +412,7 @@ fn test_expand_to_item_list() {
|
|||||||
let expansion = expand(&rules, "structs!(Foo, Bar);");
|
let expansion = expand(&rules, "structs!(Foo, Bar);");
|
||||||
let tree = token_tree_to_macro_items(&expansion).unwrap().tree();
|
let tree = token_tree_to_macro_items(&expansion).unwrap().tree();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tree.syntax().debug_dump().trim(),
|
format!("{:#?}", tree.syntax()).trim(),
|
||||||
r#"
|
r#"
|
||||||
MACRO_ITEMS@[0; 40)
|
MACRO_ITEMS@[0; 40)
|
||||||
STRUCT_DEF@[0; 20)
|
STRUCT_DEF@[0; 20)
|
||||||
@ -531,7 +531,7 @@ fn test_tt_to_stmts() {
|
|||||||
let stmts = token_tree_to_macro_stmts(&expanded).unwrap().tree();
|
let stmts = token_tree_to_macro_stmts(&expanded).unwrap().tree();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stmts.syntax().debug_dump().trim(),
|
format!("{:#?}", stmts.syntax()).trim(),
|
||||||
r#"MACRO_STMTS@[0; 15)
|
r#"MACRO_STMTS@[0; 15)
|
||||||
LET_STMT@[0; 7)
|
LET_STMT@[0; 7)
|
||||||
LET_KW@[0; 3) "let"
|
LET_KW@[0; 3) "let"
|
||||||
@ -669,7 +669,7 @@ fn test_expr_order() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
expand_to_items(&rules, "foo! { 1 + 1 }").syntax().debug_dump().trim(),
|
format!("{:#?}", expand_to_items(&rules, "foo! { 1 + 1 }").syntax()).trim(),
|
||||||
r#"MACRO_ITEMS@[0; 15)
|
r#"MACRO_ITEMS@[0; 15)
|
||||||
FN_DEF@[0; 15)
|
FN_DEF@[0; 15)
|
||||||
FN_KW@[0; 2) "fn"
|
FN_KW@[0; 2) "fn"
|
||||||
@ -1013,7 +1013,7 @@ fn test_vec() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
expand_to_expr(&rules, r#"vec![1u32,2];"#).syntax().debug_dump().trim(),
|
format!("{:#?}", expand_to_expr(&rules, r#"vec![1u32,2];"#).syntax()).trim(),
|
||||||
r#"BLOCK_EXPR@[0; 45)
|
r#"BLOCK_EXPR@[0; 45)
|
||||||
BLOCK@[0; 45)
|
BLOCK@[0; 45)
|
||||||
L_CURLY@[0; 1) "{"
|
L_CURLY@[0; 1) "{"
|
||||||
|
@ -25,7 +25,7 @@ pub fn ancestors_at_offset(
|
|||||||
) -> impl Iterator<Item = SyntaxNode> {
|
) -> impl Iterator<Item = SyntaxNode> {
|
||||||
find_token_at_offset(node, offset)
|
find_token_at_offset(node, offset)
|
||||||
.map(|token| token.parent().ancestors())
|
.map(|token| token.parent().ancestors())
|
||||||
.kmerge_by(|node1, node2| node1.range().len() < node2.range().len())
|
.kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds a node of specific Ast type at offset. Note that this is slightly
|
/// Finds a node of specific Ast type at offset. Note that this is slightly
|
||||||
|
@ -51,10 +51,10 @@ impl CheckReparse {
|
|||||||
for (a, b) in
|
for (a, b) in
|
||||||
new_parse.tree().syntax().descendants().zip(full_reparse.tree().syntax().descendants())
|
new_parse.tree().syntax().descendants().zip(full_reparse.tree().syntax().descendants())
|
||||||
{
|
{
|
||||||
if (a.kind(), a.range()) != (b.kind(), b.range()) {
|
if (a.kind(), a.text_range()) != (b.kind(), b.text_range()) {
|
||||||
eprint!("original:\n{}", parse.tree().syntax().debug_dump());
|
eprint!("original:\n{:#?}", parse.tree().syntax());
|
||||||
eprint!("reparsed:\n{}", new_parse.tree().syntax().debug_dump());
|
eprint!("reparsed:\n{:#?}", new_parse.tree().syntax());
|
||||||
eprint!("full reparse:\n{}", full_reparse.tree().syntax().debug_dump());
|
eprint!("full reparse:\n{:#?}", full_reparse.tree().syntax());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{:?}", a),
|
format!("{:?}", a),
|
||||||
format!("{:?}", b),
|
format!("{:?}", b),
|
||||||
|
@ -114,7 +114,7 @@ impl Parse<SyntaxNode> {
|
|||||||
|
|
||||||
impl Parse<SourceFile> {
|
impl Parse<SourceFile> {
|
||||||
pub fn debug_dump(&self) -> String {
|
pub fn debug_dump(&self) -> String {
|
||||||
let mut buf = self.tree().syntax().debug_dump();
|
let mut buf = format!("{:#?}", self.tree().syntax());
|
||||||
for err in self.errors.iter() {
|
for err in self.errors.iter() {
|
||||||
writeln!(buf, "error {:?}: {}", err.location(), err.kind()).unwrap();
|
writeln!(buf, "error {:?}: {}", err.location(), err.kind()).unwrap();
|
||||||
}
|
}
|
||||||
@ -234,7 +234,7 @@ fn api_walkthrough() {
|
|||||||
assert_eq!(expr_syntax.kind(), SyntaxKind::BIN_EXPR);
|
assert_eq!(expr_syntax.kind(), SyntaxKind::BIN_EXPR);
|
||||||
|
|
||||||
// And text range:
|
// And text range:
|
||||||
assert_eq!(expr_syntax.range(), TextRange::from_to(32.into(), 37.into()));
|
assert_eq!(expr_syntax.text_range(), TextRange::from_to(32.into(), 37.into()));
|
||||||
|
|
||||||
// You can get node's text as a `SyntaxText` object, which will traverse the
|
// You can get node's text as a `SyntaxText` object, which will traverse the
|
||||||
// tree collecting token's text:
|
// tree collecting token's text:
|
||||||
|
@ -46,7 +46,8 @@ fn reparse_token<'node>(
|
|||||||
WHITESPACE | COMMENT | IDENT | STRING | RAW_STRING => {
|
WHITESPACE | COMMENT | IDENT | STRING | RAW_STRING => {
|
||||||
if token.kind() == WHITESPACE || token.kind() == COMMENT {
|
if token.kind() == WHITESPACE || token.kind() == COMMENT {
|
||||||
// removing a new line may extends previous token
|
// removing a new line may extends previous token
|
||||||
if token.text().to_string()[edit.delete - token.range().start()].contains('\n') {
|
if token.text().to_string()[edit.delete - token.text_range().start()].contains('\n')
|
||||||
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,7 +63,7 @@ fn reparse_token<'node>(
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(next_char) = root.text().char_at(token.range().end()) {
|
if let Some(next_char) = root.text().char_at(token.text_range().end()) {
|
||||||
let tokens_with_next_char = tokenize(&format!("{}{}", text, next_char));
|
let tokens_with_next_char = tokenize(&format!("{}{}", text, next_char));
|
||||||
if tokens_with_next_char.len() == 1 {
|
if tokens_with_next_char.len() == 1 {
|
||||||
return None;
|
return None;
|
||||||
@ -70,7 +71,7 @@ fn reparse_token<'node>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let new_token = GreenToken::new(rowan::SyntaxKind(token.kind().into()), text.into());
|
let new_token = GreenToken::new(rowan::SyntaxKind(token.kind().into()), text.into());
|
||||||
Some((token.replace_with(new_token), token.range()))
|
Some((token.replace_with(new_token), token.text_range()))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
@ -90,11 +91,12 @@ fn reparse_block<'node>(
|
|||||||
let mut tree_sink = TextTreeSink::new(&text, &tokens);
|
let mut tree_sink = TextTreeSink::new(&text, &tokens);
|
||||||
reparser.parse(&mut token_source, &mut tree_sink);
|
reparser.parse(&mut token_source, &mut tree_sink);
|
||||||
let (green, new_errors) = tree_sink.finish();
|
let (green, new_errors) = tree_sink.finish();
|
||||||
Some((node.replace_with(green), new_errors, node.range()))
|
Some((node.replace_with(green), new_errors, node.text_range()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_text_after_edit(element: SyntaxElement, edit: &AtomTextEdit) -> String {
|
fn get_text_after_edit(element: SyntaxElement, edit: &AtomTextEdit) -> String {
|
||||||
let edit = AtomTextEdit::replace(edit.delete - element.range().start(), edit.insert.clone());
|
let edit =
|
||||||
|
AtomTextEdit::replace(edit.delete - element.text_range().start(), edit.insert.clone());
|
||||||
let text = match element {
|
let text = match element {
|
||||||
SyntaxElement::Token(token) => token.text().to_string(),
|
SyntaxElement::Token(token) => token.text().to_string(),
|
||||||
SyntaxElement::Node(node) => node.text().to_string(),
|
SyntaxElement::Node(node) => node.text().to_string(),
|
||||||
@ -188,8 +190,8 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
assert_eq_text!(
|
assert_eq_text!(
|
||||||
&fully_reparsed.tree().syntax().debug_dump(),
|
&format!("{:#?}", fully_reparsed.tree().syntax()),
|
||||||
&incrementally_reparsed.tree().syntax().debug_dump(),
|
&format!("{:#?}", incrementally_reparsed.tree().syntax()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,15 +12,15 @@ pub struct SyntaxNodePtr {
|
|||||||
|
|
||||||
impl SyntaxNodePtr {
|
impl SyntaxNodePtr {
|
||||||
pub fn new(node: &SyntaxNode) -> SyntaxNodePtr {
|
pub fn new(node: &SyntaxNode) -> SyntaxNodePtr {
|
||||||
SyntaxNodePtr { range: node.range(), kind: node.kind() }
|
SyntaxNodePtr { range: node.text_range(), kind: node.kind() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_node(self, root: &SyntaxNode) -> SyntaxNode {
|
pub fn to_node(self, root: &SyntaxNode) -> SyntaxNode {
|
||||||
assert!(root.parent().is_none());
|
assert!(root.parent().is_none());
|
||||||
successors(Some(root.clone()), |node| {
|
successors(Some(root.clone()), |node| {
|
||||||
node.children().find(|it| self.range.is_subrange(&it.range()))
|
node.children().find(|it| self.range.is_subrange(&it.text_range()))
|
||||||
})
|
})
|
||||||
.find(|it| it.range() == self.range && it.kind() == self.kind)
|
.find(|it| it.text_range() == self.range && it.kind() == self.kind)
|
||||||
.unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self))
|
.unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,11 +6,7 @@
|
|||||||
//! The *real* implementation is in the (language-agnostic) `rowan` crate, this
|
//! The *real* implementation is in the (language-agnostic) `rowan` crate, this
|
||||||
//! modules just wraps its API.
|
//! modules just wraps its API.
|
||||||
|
|
||||||
use std::{
|
use std::{fmt, iter::successors, ops::RangeInclusive};
|
||||||
fmt::{self, Write},
|
|
||||||
iter::successors,
|
|
||||||
ops::RangeInclusive,
|
|
||||||
};
|
|
||||||
|
|
||||||
use ra_parser::ParseError;
|
use ra_parser::ParseError;
|
||||||
use rowan::GreenNodeBuilder;
|
use rowan::GreenNodeBuilder;
|
||||||
@ -36,8 +32,29 @@ pub enum InsertPosition<T> {
|
|||||||
pub struct SyntaxNode(pub(crate) rowan::cursor::SyntaxNode);
|
pub struct SyntaxNode(pub(crate) rowan::cursor::SyntaxNode);
|
||||||
|
|
||||||
impl fmt::Debug for SyntaxNode {
|
impl fmt::Debug for SyntaxNode {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(fmt, "{:?}@{:?}", self.kind(), self.range())
|
if f.alternate() {
|
||||||
|
let mut level = 0;
|
||||||
|
for event in self.preorder_with_tokens() {
|
||||||
|
match event {
|
||||||
|
WalkEvent::Enter(element) => {
|
||||||
|
for _ in 0..level {
|
||||||
|
write!(f, " ")?;
|
||||||
|
}
|
||||||
|
match element {
|
||||||
|
SyntaxElement::Node(node) => writeln!(f, "{:?}", node)?,
|
||||||
|
SyntaxElement::Token(token) => writeln!(f, "{:?}", token)?,
|
||||||
|
}
|
||||||
|
level += 1;
|
||||||
|
}
|
||||||
|
WalkEvent::Leave(_) => level -= 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert_eq!(level, 0);
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
write!(f, "{:?}@{:?}", self.kind(), self.text_range())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +80,7 @@ impl SyntaxNode {
|
|||||||
self.0.kind().0.into()
|
self.0.kind().0.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn range(&self) -> TextRange {
|
pub fn text_range(&self) -> TextRange {
|
||||||
self.0.text_range()
|
self.0.text_range()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,31 +190,6 @@ impl SyntaxNode {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn debug_dump(&self) -> String {
|
|
||||||
let mut level = 0;
|
|
||||||
let mut buf = String::new();
|
|
||||||
|
|
||||||
for event in self.preorder_with_tokens() {
|
|
||||||
match event {
|
|
||||||
WalkEvent::Enter(element) => {
|
|
||||||
for _ in 0..level {
|
|
||||||
buf.push_str(" ");
|
|
||||||
}
|
|
||||||
match element {
|
|
||||||
SyntaxElement::Node(node) => writeln!(buf, "{:?}", node).unwrap(),
|
|
||||||
SyntaxElement::Token(token) => writeln!(buf, "{:?}", token).unwrap(),
|
|
||||||
}
|
|
||||||
level += 1;
|
|
||||||
}
|
|
||||||
WalkEvent::Leave(_) => level -= 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(level, 0);
|
|
||||||
|
|
||||||
buf
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn replace_with(&self, replacement: GreenNode) -> GreenNode {
|
pub(crate) fn replace_with(&self, replacement: GreenNode) -> GreenNode {
|
||||||
self.0.replace_with(replacement)
|
self.0.replace_with(replacement)
|
||||||
}
|
}
|
||||||
@ -299,7 +291,7 @@ pub struct SyntaxToken(pub(crate) rowan::cursor::SyntaxToken);
|
|||||||
|
|
||||||
impl fmt::Debug for SyntaxToken {
|
impl fmt::Debug for SyntaxToken {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(fmt, "{:?}@{:?}", self.kind(), self.range())?;
|
write!(fmt, "{:?}@{:?}", self.kind(), self.text_range())?;
|
||||||
if self.text().len() < 25 {
|
if self.text().len() < 25 {
|
||||||
return write!(fmt, " {:?}", self.text());
|
return write!(fmt, " {:?}", self.text());
|
||||||
}
|
}
|
||||||
@ -329,7 +321,7 @@ impl SyntaxToken {
|
|||||||
self.0.text()
|
self.0.text()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn range(&self) -> TextRange {
|
pub fn text_range(&self) -> TextRange {
|
||||||
self.0.text_range()
|
self.0.text_range()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,10 +453,10 @@ impl SyntaxElement {
|
|||||||
.ancestors()
|
.ancestors()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn range(&self) -> TextRange {
|
pub fn text_range(&self) -> TextRange {
|
||||||
match self {
|
match self {
|
||||||
SyntaxElement::Node(it) => it.range(),
|
SyntaxElement::Node(it) => it.text_range(),
|
||||||
SyntaxElement::Token(it) => it.range(),
|
SyntaxElement::Token(it) => it.text_range(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ pub struct SyntaxText {
|
|||||||
|
|
||||||
impl SyntaxText {
|
impl SyntaxText {
|
||||||
pub(crate) fn new(node: SyntaxNode) -> SyntaxText {
|
pub(crate) fn new(node: SyntaxNode) -> SyntaxText {
|
||||||
let range = node.range();
|
let range = node.text_range();
|
||||||
SyntaxText { node, range }
|
SyntaxText { node, range }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,14 +24,14 @@ impl SyntaxText {
|
|||||||
self.node.descendants_with_tokens().try_fold(init, move |acc, element| {
|
self.node.descendants_with_tokens().try_fold(init, move |acc, element| {
|
||||||
let res = match element {
|
let res = match element {
|
||||||
SyntaxElement::Token(token) => {
|
SyntaxElement::Token(token) => {
|
||||||
let range = match self.range.intersection(&token.range()) {
|
let range = match self.range.intersection(&token.text_range()) {
|
||||||
None => return Ok(acc),
|
None => return Ok(acc),
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
};
|
};
|
||||||
let slice = if range == token.range() {
|
let slice = if range == token.text_range() {
|
||||||
token.text()
|
token.text()
|
||||||
} else {
|
} else {
|
||||||
let range = range - token.range().start();
|
let range = range - token.text_range().start();
|
||||||
&token.text()[range]
|
&token.text()[range]
|
||||||
};
|
};
|
||||||
f(acc, slice)?
|
f(acc, slice)?
|
||||||
|
@ -33,7 +33,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
|
|||||||
if let Some(end) = text.rfind('\'') {
|
if let Some(end) = text.rfind('\'') {
|
||||||
if let Some(without_quotes) = text.get(2..end) {
|
if let Some(without_quotes) = text.get(2..end) {
|
||||||
if let Err((off, err)) = unescape::unescape_byte(without_quotes) {
|
if let Err((off, err)) = unescape::unescape_byte(without_quotes) {
|
||||||
let off = token.range().start() + TextUnit::from_usize(off + 2);
|
let off = token.text_range().start() + TextUnit::from_usize(off + 2);
|
||||||
acc.push(SyntaxError::new(err.into(), off))
|
acc.push(SyntaxError::new(err.into(), off))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,7 +43,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
|
|||||||
if let Some(end) = text.rfind('\'') {
|
if let Some(end) = text.rfind('\'') {
|
||||||
if let Some(without_quotes) = text.get(1..end) {
|
if let Some(without_quotes) = text.get(1..end) {
|
||||||
if let Err((off, err)) = unescape::unescape_char(without_quotes) {
|
if let Err((off, err)) = unescape::unescape_char(without_quotes) {
|
||||||
let off = token.range().start() + TextUnit::from_usize(off + 1);
|
let off = token.text_range().start() + TextUnit::from_usize(off + 1);
|
||||||
acc.push(SyntaxError::new(err.into(), off))
|
acc.push(SyntaxError::new(err.into(), off))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,7 +55,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
|
|||||||
unescape::unescape_byte_str(without_quotes, &mut |range, char| {
|
unescape::unescape_byte_str(without_quotes, &mut |range, char| {
|
||||||
if let Err(err) = char {
|
if let Err(err) = char {
|
||||||
let off = range.start;
|
let off = range.start;
|
||||||
let off = token.range().start() + TextUnit::from_usize(off + 2);
|
let off = token.text_range().start() + TextUnit::from_usize(off + 2);
|
||||||
acc.push(SyntaxError::new(err.into(), off))
|
acc.push(SyntaxError::new(err.into(), off))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -68,7 +68,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
|
|||||||
unescape::unescape_str(without_quotes, &mut |range, char| {
|
unescape::unescape_str(without_quotes, &mut |range, char| {
|
||||||
if let Err(err) = char {
|
if let Err(err) = char {
|
||||||
let off = range.start;
|
let off = range.start;
|
||||||
let off = token.range().start() + TextUnit::from_usize(off + 1);
|
let off = token.text_range().start() + TextUnit::from_usize(off + 1);
|
||||||
acc.push(SyntaxError::new(err.into(), off))
|
acc.push(SyntaxError::new(err.into(), off))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -89,9 +89,9 @@ pub(crate) fn validate_block_structure(root: &SyntaxNode) {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
node.parent(),
|
node.parent(),
|
||||||
pair.parent(),
|
pair.parent(),
|
||||||
"\nunpaired curleys:\n{}\n{}\n",
|
"\nunpaired curleys:\n{}\n{:#?}\n",
|
||||||
root.text(),
|
root.text(),
|
||||||
root.debug_dump(),
|
root,
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
node.next_sibling().is_none() && pair.prev_sibling().is_none(),
|
node.next_sibling().is_none() && pair.prev_sibling().is_none(),
|
||||||
|
@ -16,6 +16,7 @@ pub(crate) fn validate_block_node(node: ast::Block, errors: &mut Vec<SyntaxError
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
errors
|
errors.extend(
|
||||||
.extend(node.attrs().map(|attr| SyntaxError::new(InvalidBlockAttr, attr.syntax().range())))
|
node.attrs().map(|attr| SyntaxError::new(InvalidBlockAttr, attr.syntax().text_range())),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
pub(crate) fn validate_field_expr_node(node: ast::FieldExpr, errors: &mut Vec<SyntaxError>) {
|
pub(crate) fn validate_field_expr_node(node: ast::FieldExpr, errors: &mut Vec<SyntaxError>) {
|
||||||
if let Some(FieldKind::Index(idx)) = node.field_access() {
|
if let Some(FieldKind::Index(idx)) = node.field_access() {
|
||||||
if idx.text().chars().any(|c| c < '0' || c > '9') {
|
if idx.text().chars().any(|c| c < '0' || c > '9') {
|
||||||
errors.push(SyntaxError::new(InvalidTupleIndexFormat, idx.range()));
|
errors.push(SyntaxError::new(InvalidTupleIndexFormat, idx.text_range()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user