-
Notifications
You must be signed in to change notification settings - Fork 92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Subsequent RewriteRules don't transform elements added in previous transform. #257
Comments
Indeed, this is a known issue. On the Getting started page, it is written:
There's a chance that new RuleTransformer(
addThingElement(),
addNewElement()
) If that's not it, then indeed, it's probably that you need to call the transformer on the new elements yourself: ...
case <element>{ children@_*}</element> => <element>{ change(children) }</element> |
@ndelargy I hope I was able to help and you were able to make progress. Thanks you for giving a simple example case. |
I'll keep this open, since it would be helpful if someone investigated whether fixing this is possible. |
Hi @ashawley thanks for getting back so quick on this... |
The problem is that However, following rules will apply on the way back from recursion. For example:
If you call If class RuleTransformer(rules: RewriteRule*) extends BasicTransformer {
override def transform(n: Node): Seq[Node] = {
rules.foldLeft(n: Seq[Node]) { (res, rule) => rule transform res.flatMap(super.transform) }
}
} However, it would through a stack overflow exception on the example I gave. The only solution I see is break the relationship between class NestingTransformer(rule: RewriteRule) extends BasicTransformer {
override def transform(n: Node): Seq[Node] = {
rule.transform(super.transform(n))
}
}
class RuleTransformer(rules: RewriteRule*) {
val nestingTransformers = rules.map(new NestingTransformer(_))
def transform(n: Node): Seq[Node] = {
nestingTransformers.foldLeft(n: Seq[Node]) { (res, transformer) =>
transformer.transform(res)
}
}
} Fun fact: I can't see a case for the exact semantics that |
RuleTransformer for the past eleven years or more has first recursed, then applied the rewrite rules as it backed out of the recursion. That prevented rewrite rules from acting on changes of previous rules unless they recursed themselves. The workaround has always been chain rule transformers instead of calling one rule transformer with all the rules. This change basically re-implements RuleTransformer as that workaround, and introduces a NestingTransformer which does the nesting. Clearly, if you have N rules you'll now recurse N times instead of once, though each rule is still only applied once for each element. On the other hand, a RewriteRule that recursed would incur in exponential times, and now they don't need to. The original behavior has no reason to be. It didn't prevent rules from seeing each other changes, nor was it particularly concerned with performance. With API changes coming on 2.0, I believe this is the right time to introduce this change.
Make RuleTransformer fully recursive [#257]
When we apply a transform with two rewrite rules: the first one adding a new element, the second one adding children to the new element; then the second rewrite rule does not match on the elements added in the first rule.
When we apply the same RewriteRules in two separate RuleTransformers it does add the children to the elements added in the first step. We would expect the
change
andchangeWorkaround
functions to produce the same output.The text was updated successfully, but these errors were encountered: