mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-08-22 11:24:24 +00:00
internal: remove SyntaxRewriter
This commit is contained in:
parent
873717190d
commit
73123a7550
3 changed files with 7 additions and 154 deletions
|
@ -42,10 +42,12 @@ pub fn try_merge_imports(
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let lhs = lhs.clone_subtree().clone_for_update();
|
||||||
let lhs_tree = lhs.use_tree()?;
|
let lhs_tree = lhs.use_tree()?;
|
||||||
let rhs_tree = rhs.use_tree()?;
|
let rhs_tree = rhs.use_tree()?;
|
||||||
let merged = try_merge_trees(&lhs_tree, &rhs_tree, merge_behavior)?;
|
let merged = try_merge_trees(&lhs_tree, &rhs_tree, merge_behavior)?;
|
||||||
Some(lhs.with_use_tree(merged).clone_for_update())
|
ted::replace(lhs_tree.syntax(), merged.syntax());
|
||||||
|
Some(lhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_merge_trees(
|
pub fn try_merge_trees(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! FIXME: write short doc here
|
//! FIXME: write short doc here
|
||||||
|
|
||||||
use std::{fmt, hash::BuildHasherDefault, ops::RangeInclusive};
|
use std::{hash::BuildHasherDefault, ops::RangeInclusive};
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
@ -330,110 +330,6 @@ fn _replace_children(
|
||||||
with_children(parent, new_children)
|
with_children(parent, new_children)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
|
||||||
enum InsertPos {
|
|
||||||
FirstChildOf(SyntaxNode),
|
|
||||||
After(SyntaxElement),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub(crate) struct SyntaxRewriter<'a> {
|
|
||||||
//FIXME: add debug_assertions that all elements are in fact from the same file.
|
|
||||||
replacements: FxHashMap<SyntaxElement, Replacement>,
|
|
||||||
insertions: IndexMap<InsertPos, Vec<SyntaxElement>>,
|
|
||||||
_pd: std::marker::PhantomData<&'a ()>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for SyntaxRewriter<'_> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
f.debug_struct("SyntaxRewriter")
|
|
||||||
.field("replacements", &self.replacements)
|
|
||||||
.field("insertions", &self.insertions)
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SyntaxRewriter<'_> {
|
|
||||||
pub(crate) fn replace<T: Clone + Into<SyntaxElement>>(&mut self, what: &T, with: &T) {
|
|
||||||
let what = what.clone().into();
|
|
||||||
let replacement = Replacement::Single(with.clone().into());
|
|
||||||
self.replacements.insert(what, replacement);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn rewrite(&self, node: &SyntaxNode) -> SyntaxNode {
|
|
||||||
let _p = profile::span("rewrite");
|
|
||||||
|
|
||||||
if self.replacements.is_empty() && self.insertions.is_empty() {
|
|
||||||
return node.clone();
|
|
||||||
}
|
|
||||||
let green = self.rewrite_children(node);
|
|
||||||
with_green(node, green)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn rewrite_ast<N: AstNode>(self, node: &N) -> N {
|
|
||||||
N::cast(self.rewrite(node.syntax())).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn replacement(&self, element: &SyntaxElement) -> Option<Replacement> {
|
|
||||||
self.replacements.get(element).cloned()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn insertions(&self, pos: &InsertPos) -> Option<impl Iterator<Item = SyntaxElement> + '_> {
|
|
||||||
self.insertions.get(pos).map(|insertions| insertions.iter().cloned())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rewrite_children(&self, node: &SyntaxNode) -> rowan::GreenNode {
|
|
||||||
let _p = profile::span("rewrite_children");
|
|
||||||
|
|
||||||
// FIXME: this could be made much faster.
|
|
||||||
let mut new_children = Vec::new();
|
|
||||||
if let Some(elements) = self.insertions(&InsertPos::FirstChildOf(node.clone())) {
|
|
||||||
new_children.extend(elements.map(element_to_green));
|
|
||||||
}
|
|
||||||
for child in node.children_with_tokens() {
|
|
||||||
self.rewrite_self(&mut new_children, &child);
|
|
||||||
}
|
|
||||||
|
|
||||||
rowan::GreenNode::new(rowan::SyntaxKind(node.kind() as u16), new_children)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rewrite_self(
|
|
||||||
&self,
|
|
||||||
acc: &mut Vec<NodeOrToken<rowan::GreenNode, rowan::GreenToken>>,
|
|
||||||
element: &SyntaxElement,
|
|
||||||
) {
|
|
||||||
let _p = profile::span("rewrite_self");
|
|
||||||
|
|
||||||
if let Some(replacement) = self.replacement(&element) {
|
|
||||||
match replacement {
|
|
||||||
Replacement::Single(element) => acc.push(element_to_green(element)),
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
match element {
|
|
||||||
NodeOrToken::Token(it) => acc.push(NodeOrToken::Token(it.green().to_owned())),
|
|
||||||
NodeOrToken::Node(it) => {
|
|
||||||
acc.push(NodeOrToken::Node(self.rewrite_children(it)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(elements) = self.insertions(&InsertPos::After(element.clone())) {
|
|
||||||
acc.extend(elements.map(element_to_green));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn element_to_green(element: SyntaxElement) -> NodeOrToken<rowan::GreenNode, rowan::GreenToken> {
|
|
||||||
match element {
|
|
||||||
NodeOrToken::Node(it) => NodeOrToken::Node(it.green().into_owned()),
|
|
||||||
NodeOrToken::Token(it) => NodeOrToken::Token(it.green().to_owned()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
enum Replacement {
|
|
||||||
Single(SyntaxElement),
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with_children(
|
fn with_children(
|
||||||
parent: &SyntaxNode,
|
parent: &SyntaxNode,
|
||||||
new_children: Vec<NodeOrToken<rowan::GreenNode, rowan::GreenToken>>,
|
new_children: Vec<NodeOrToken<rowan::GreenNode, rowan::GreenToken>>,
|
||||||
|
|
|
@ -2,18 +2,18 @@
|
||||||
//! immutable, all function here return a fresh copy of the tree, instead of
|
//! immutable, all function here return a fresh copy of the tree, instead of
|
||||||
//! doing an in-place modification.
|
//! doing an in-place modification.
|
||||||
use std::{
|
use std::{
|
||||||
array, fmt, iter,
|
fmt, iter,
|
||||||
ops::{self, RangeInclusive},
|
ops::{self, RangeInclusive},
|
||||||
};
|
};
|
||||||
|
|
||||||
use arrayvec::ArrayVec;
|
use arrayvec::ArrayVec;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
algo::{self, SyntaxRewriter},
|
algo,
|
||||||
ast::{
|
ast::{
|
||||||
self,
|
self,
|
||||||
make::{self, tokens},
|
make::{self, tokens},
|
||||||
AstNode, GenericParamsOwner, NameOwner, TypeBoundsOwner,
|
AstNode, TypeBoundsOwner,
|
||||||
},
|
},
|
||||||
ted, AstToken, Direction, InsertPosition, NodeOrToken, SmolStr, SyntaxElement, SyntaxKind,
|
ted, AstToken, Direction, InsertPosition, NodeOrToken, SmolStr, SyntaxElement, SyntaxKind,
|
||||||
SyntaxKind::{ATTR, COMMENT, WHITESPACE},
|
SyntaxKind::{ATTR, COMMENT, WHITESPACE},
|
||||||
|
@ -46,18 +46,6 @@ impl ast::Fn {
|
||||||
to_insert.push(body.syntax().clone().into());
|
to_insert.push(body.syntax().clone().into());
|
||||||
self.replace_children(single_node(old_body_or_semi), to_insert)
|
self.replace_children(single_node(old_body_or_semi), to_insert)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn with_generic_param_list(&self, generic_args: ast::GenericParamList) -> ast::Fn {
|
|
||||||
if let Some(old) = self.generic_param_list() {
|
|
||||||
return self.replace_descendant(old, generic_args);
|
|
||||||
}
|
|
||||||
|
|
||||||
let anchor = self.name().expect("The function must have a name").syntax().clone();
|
|
||||||
|
|
||||||
let to_insert = [generic_args.syntax().clone().into()];
|
|
||||||
self.insert_children(InsertPosition::After(anchor.into()), array::IntoIter::new(to_insert))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_multiline<N>(node: N) -> N
|
fn make_multiline<N>(node: N) -> N
|
||||||
|
@ -313,33 +301,7 @@ impl ast::PathSegment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ast::Use {
|
|
||||||
#[must_use]
|
|
||||||
pub fn with_use_tree(&self, use_tree: ast::UseTree) -> ast::Use {
|
|
||||||
if let Some(old) = self.use_tree() {
|
|
||||||
return self.replace_descendant(old, use_tree);
|
|
||||||
}
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ast::UseTree {
|
impl ast::UseTree {
|
||||||
#[must_use]
|
|
||||||
pub fn with_path(&self, path: ast::Path) -> ast::UseTree {
|
|
||||||
if let Some(old) = self.path() {
|
|
||||||
return self.replace_descendant(old, path);
|
|
||||||
}
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn with_use_tree_list(&self, use_tree_list: ast::UseTreeList) -> ast::UseTree {
|
|
||||||
if let Some(old) = self.use_tree_list() {
|
|
||||||
return self.replace_descendant(old, use_tree_list);
|
|
||||||
}
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Splits off the given prefix, making it the path component of the use tree, appending the rest of the path to all UseTreeList items.
|
/// 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]
|
#[must_use]
|
||||||
pub fn split_prefix(&self, prefix: &ast::Path) -> ast::UseTree {
|
pub fn split_prefix(&self, prefix: &ast::Path) -> ast::UseTree {
|
||||||
|
@ -664,13 +626,6 @@ pub trait AstNodeEdit: AstNode + Clone + Sized {
|
||||||
let new_syntax = algo::replace_children(self.syntax(), to_replace, to_insert);
|
let new_syntax = algo::replace_children(self.syntax(), to_replace, to_insert);
|
||||||
Self::cast(new_syntax).unwrap()
|
Self::cast(new_syntax).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
fn replace_descendant<D: AstNode>(&self, old: D, new: D) -> Self {
|
|
||||||
let mut rewriter = SyntaxRewriter::default();
|
|
||||||
rewriter.replace(old.syntax(), new.syntax());
|
|
||||||
rewriter.rewrite_ast(self)
|
|
||||||
}
|
|
||||||
fn indent_level(&self) -> IndentLevel {
|
fn indent_level(&self) -> IndentLevel {
|
||||||
IndentLevel::from_node(self.syntax())
|
IndentLevel::from_node(self.syntax())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue