mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-08-15 16:11:01 +00:00
Use mutable syntax trees in merge_imports
, split_imports
This commit is contained in:
parent
4c20d6879f
commit
601413df8f
7 changed files with 144 additions and 113 deletions
|
@ -4,48 +4,10 @@
|
|||
use std::{fmt, iter, ops};
|
||||
|
||||
use crate::{
|
||||
algo,
|
||||
ast::{self, make, AstNode},
|
||||
ted, AstToken, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken,
|
||||
};
|
||||
|
||||
impl ast::UseTree {
|
||||
/// Splits off the given prefix, making it the path component of the use tree, appending the rest of the path to all UseTreeList items.
|
||||
#[must_use]
|
||||
pub fn split_prefix(&self, prefix: &ast::Path) -> ast::UseTree {
|
||||
let suffix = if self.path().as_ref() == Some(prefix) && self.use_tree_list().is_none() {
|
||||
make::path_unqualified(make::path_segment_self())
|
||||
} else {
|
||||
match split_path_prefix(prefix) {
|
||||
Some(it) => it,
|
||||
None => return self.clone(),
|
||||
}
|
||||
};
|
||||
|
||||
let use_tree = make::use_tree(
|
||||
suffix,
|
||||
self.use_tree_list(),
|
||||
self.rename(),
|
||||
self.star_token().is_some(),
|
||||
);
|
||||
let nested = make::use_tree_list(iter::once(use_tree));
|
||||
return make::use_tree(prefix.clone(), Some(nested), None, false);
|
||||
|
||||
fn split_path_prefix(prefix: &ast::Path) -> Option<ast::Path> {
|
||||
let parent = prefix.parent_path()?;
|
||||
let segment = parent.segment()?;
|
||||
if algo::has_errors(segment.syntax()) {
|
||||
return None;
|
||||
}
|
||||
let mut res = make::path_unqualified(segment);
|
||||
for p in iter::successors(parent.parent_path(), |it| it.parent_path()) {
|
||||
res = make::path_qualified(res, p.segment()?);
|
||||
}
|
||||
Some(res)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct IndentLevel(pub u8);
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
//! Structural editing for ast.
|
||||
|
||||
use std::iter::empty;
|
||||
use std::iter::{empty, successors};
|
||||
|
||||
use parser::{SyntaxKind, T};
|
||||
use rowan::SyntaxElement;
|
||||
|
||||
use crate::{
|
||||
algo::neighbor,
|
||||
algo::{self, neighbor},
|
||||
ast::{self, edit::IndentLevel, make, HasGenericParams},
|
||||
ted::{self, Position},
|
||||
AstNode, AstToken, Direction,
|
||||
|
@ -282,6 +282,78 @@ impl ast::UseTree {
|
|||
}
|
||||
ted::remove(self.syntax());
|
||||
}
|
||||
|
||||
pub fn get_or_create_use_tree_list(&self) -> ast::UseTreeList {
|
||||
match self.use_tree_list() {
|
||||
Some(it) => it,
|
||||
None => {
|
||||
let position = Position::last_child_of(self.syntax());
|
||||
let use_tree_list = make::use_tree_list(empty()).clone_for_update();
|
||||
let mut elements = Vec::with_capacity(2);
|
||||
if self.coloncolon_token().is_none() {
|
||||
elements.push(make::token(T![::]).into());
|
||||
}
|
||||
elements.push(use_tree_list.syntax().clone().into());
|
||||
ted::insert_all_raw(position, elements);
|
||||
use_tree_list
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Splits off the given prefix, making it the path component of the use tree,
|
||||
/// appending the rest of the path to all UseTreeList items.
|
||||
pub fn split_prefix(&self, prefix: &ast::Path) {
|
||||
debug_assert_eq!(self.path(), Some(prefix.top_path()));
|
||||
let path = self.path().unwrap();
|
||||
if &path == prefix && self.use_tree_list().is_none() {
|
||||
let self_suffix = make::path_unqualified(make::path_segment_self()).clone_for_update();
|
||||
ted::replace(path.syntax(), self_suffix.syntax());
|
||||
} else if split_path_prefix(prefix).is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
let subtree = self.clone_subtree().clone_for_update();
|
||||
ted::remove_all_iter(self.syntax().children_with_tokens());
|
||||
ted::insert(Position::first_child_of(self.syntax()), prefix.syntax());
|
||||
self.get_or_create_use_tree_list().add_use_tree(subtree);
|
||||
|
||||
fn split_path_prefix(prefix: &ast::Path) -> Option<()> {
|
||||
let parent = prefix.parent_path()?;
|
||||
let segment = parent.segment()?;
|
||||
if algo::has_errors(segment.syntax()) {
|
||||
return None;
|
||||
}
|
||||
for p in successors(parent.parent_path(), |it| it.parent_path()) {
|
||||
p.segment()?;
|
||||
}
|
||||
prefix.parent_path().and_then(|p| p.coloncolon_token()).map(ted::remove);
|
||||
ted::remove(prefix.syntax());
|
||||
Some(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ast::UseTreeList {
|
||||
pub fn add_use_tree(&self, use_tree: ast::UseTree) {
|
||||
let (position, elements) = match self.use_trees().last() {
|
||||
Some(last_tree) => (
|
||||
Position::after(last_tree.syntax()),
|
||||
vec![
|
||||
make::token(T![,]).into(),
|
||||
make::tokens::single_space().into(),
|
||||
use_tree.syntax.into(),
|
||||
],
|
||||
),
|
||||
None => {
|
||||
let position = match self.l_curly_token() {
|
||||
Some(l_curly) => Position::after(l_curly),
|
||||
None => Position::last_child_of(self.syntax()),
|
||||
};
|
||||
(position, vec![use_tree.syntax.into()])
|
||||
}
|
||||
};
|
||||
ted::insert_all_raw(position, elements);
|
||||
}
|
||||
}
|
||||
|
||||
impl ast::Use {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue