Skip to content

Commit 03dcf51

Browse files
bors[bot]matklad
andauthored
Merge #6125
6125: Simplify ast_transform r=matklad a=matklad bors r+ 🤖 Co-authored-by: Aleksey Kladov <[email protected]>
2 parents 673e1dd + 3290bb4 commit 03dcf51

File tree

1 file changed

+34
-40
lines changed

1 file changed

+34
-40
lines changed

crates/assists/src/ast_transform.rs

+34-40
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@ use hir::{HirDisplay, PathResolution, SemanticsScope};
55
use syntax::{
66
algo::SyntaxRewriter,
77
ast::{self, AstNode},
8+
SyntaxNode,
89
};
910

1011
pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: N) -> N {
1112
SyntaxRewriter::from_fn(|element| match element {
1213
syntax::SyntaxElement::Node(n) => {
13-
let replacement = transformer.get_substitution(&n)?;
14+
let replacement = transformer.get_substitution(&n, transformer)?;
1415
Some(replacement.into())
1516
}
1617
_ => None,
@@ -47,32 +48,35 @@ pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: N) -> N {
4748
/// We'd want to somehow express this concept simpler, but so far nobody got to
4849
/// simplifying this!
4950
pub trait AstTransform<'a> {
50-
fn get_substitution(&self, node: &syntax::SyntaxNode) -> Option<syntax::SyntaxNode>;
51+
fn get_substitution(
52+
&self,
53+
node: &SyntaxNode,
54+
recur: &dyn AstTransform<'a>,
55+
) -> Option<SyntaxNode>;
5156

52-
fn chain_before(self, other: Box<dyn AstTransform<'a> + 'a>) -> Box<dyn AstTransform<'a> + 'a>;
5357
fn or<T: AstTransform<'a> + 'a>(self, other: T) -> Box<dyn AstTransform<'a> + 'a>
5458
where
5559
Self: Sized + 'a,
5660
{
57-
self.chain_before(Box::new(other))
61+
Box::new(Or(Box::new(self), Box::new(other)))
5862
}
5963
}
6064

61-
struct NullTransformer;
65+
struct Or<'a>(Box<dyn AstTransform<'a> + 'a>, Box<dyn AstTransform<'a> + 'a>);
6266

63-
impl<'a> AstTransform<'a> for NullTransformer {
64-
fn get_substitution(&self, _node: &syntax::SyntaxNode) -> Option<syntax::SyntaxNode> {
65-
None
66-
}
67-
fn chain_before(self, other: Box<dyn AstTransform<'a> + 'a>) -> Box<dyn AstTransform<'a> + 'a> {
68-
other
67+
impl<'a> AstTransform<'a> for Or<'a> {
68+
fn get_substitution(
69+
&self,
70+
node: &SyntaxNode,
71+
recur: &dyn AstTransform<'a>,
72+
) -> Option<SyntaxNode> {
73+
self.0.get_substitution(node, recur).or_else(|| self.1.get_substitution(node, recur))
6974
}
7075
}
7176

7277
pub struct SubstituteTypeParams<'a> {
7378
source_scope: &'a SemanticsScope<'a>,
7479
substs: FxHashMap<hir::TypeParam, ast::Type>,
75-
previous: Box<dyn AstTransform<'a> + 'a>,
7680
}
7781

7882
impl<'a> SubstituteTypeParams<'a> {
@@ -111,11 +115,7 @@ impl<'a> SubstituteTypeParams<'a> {
111115
}
112116
})
113117
.collect();
114-
return SubstituteTypeParams {
115-
source_scope,
116-
substs: substs_by_param,
117-
previous: Box::new(NullTransformer),
118-
};
118+
return SubstituteTypeParams { source_scope, substs: substs_by_param };
119119

120120
// FIXME: It would probably be nicer if we could get this via HIR (i.e. get the
121121
// trait ref, and then go from the types in the substs back to the syntax).
@@ -140,7 +140,14 @@ impl<'a> SubstituteTypeParams<'a> {
140140
Some(result)
141141
}
142142
}
143-
fn get_substitution_inner(&self, node: &syntax::SyntaxNode) -> Option<syntax::SyntaxNode> {
143+
}
144+
145+
impl<'a> AstTransform<'a> for SubstituteTypeParams<'a> {
146+
fn get_substitution(
147+
&self,
148+
node: &SyntaxNode,
149+
_recur: &dyn AstTransform<'a>,
150+
) -> Option<SyntaxNode> {
144151
let type_ref = ast::Type::cast(node.clone())?;
145152
let path = match &type_ref {
146153
ast::Type::PathType(path_type) => path_type.path()?,
@@ -154,27 +161,23 @@ impl<'a> SubstituteTypeParams<'a> {
154161
}
155162
}
156163

157-
impl<'a> AstTransform<'a> for SubstituteTypeParams<'a> {
158-
fn get_substitution(&self, node: &syntax::SyntaxNode) -> Option<syntax::SyntaxNode> {
159-
self.get_substitution_inner(node).or_else(|| self.previous.get_substitution(node))
160-
}
161-
fn chain_before(self, other: Box<dyn AstTransform<'a> + 'a>) -> Box<dyn AstTransform<'a> + 'a> {
162-
Box::new(SubstituteTypeParams { previous: other, ..self })
163-
}
164-
}
165-
166164
pub struct QualifyPaths<'a> {
167165
target_scope: &'a SemanticsScope<'a>,
168166
source_scope: &'a SemanticsScope<'a>,
169-
previous: Box<dyn AstTransform<'a> + 'a>,
170167
}
171168

172169
impl<'a> QualifyPaths<'a> {
173170
pub fn new(target_scope: &'a SemanticsScope<'a>, source_scope: &'a SemanticsScope<'a>) -> Self {
174-
Self { target_scope, source_scope, previous: Box::new(NullTransformer) }
171+
Self { target_scope, source_scope }
175172
}
173+
}
176174

177-
fn get_substitution_inner(&self, node: &syntax::SyntaxNode) -> Option<syntax::SyntaxNode> {
175+
impl<'a> AstTransform<'a> for QualifyPaths<'a> {
176+
fn get_substitution(
177+
&self,
178+
node: &SyntaxNode,
179+
recur: &dyn AstTransform<'a>,
180+
) -> Option<SyntaxNode> {
178181
// FIXME handle value ns?
179182
let from = self.target_scope.module()?;
180183
let p = ast::Path::cast(node.clone())?;
@@ -191,7 +194,7 @@ impl<'a> QualifyPaths<'a> {
191194
let type_args = p
192195
.segment()
193196
.and_then(|s| s.generic_arg_list())
194-
.map(|arg_list| apply(self, arg_list));
197+
.map(|arg_list| apply(recur, arg_list));
195198
if let Some(type_args) = type_args {
196199
let last_segment = path.segment().unwrap();
197200
path = path.with_segment(last_segment.with_generic_args(type_args))
@@ -208,15 +211,6 @@ impl<'a> QualifyPaths<'a> {
208211
}
209212
}
210213

211-
impl<'a> AstTransform<'a> for QualifyPaths<'a> {
212-
fn get_substitution(&self, node: &syntax::SyntaxNode) -> Option<syntax::SyntaxNode> {
213-
self.get_substitution_inner(node).or_else(|| self.previous.get_substitution(node))
214-
}
215-
fn chain_before(self, other: Box<dyn AstTransform<'a> + 'a>) -> Box<dyn AstTransform<'a> + 'a> {
216-
Box::new(QualifyPaths { previous: other, ..self })
217-
}
218-
}
219-
220214
pub(crate) fn path_to_ast(path: hir::ModPath) -> ast::Path {
221215
let parse = ast::SourceFile::parse(&path.to_string());
222216
parse

0 commit comments

Comments
 (0)