[core] Deprecate jjtree methods from the Node interface#2172
Conversation
Use raw supertype to avoid conflicts
4683801 to
87eaaef
Compare
Generated by 🚫 Danger |
adangel
left a comment
There was a problem hiding this comment.
I think, that's the right direction for the Node interface. 👍 Have a look at my comments, maybe we can improve the API further.
I don't think we should expose tokens as an API yet. They're an implementation detail, not used much, and the AST should be able to reflect all the information that can be found in the tokens. The methods of AbstractNode can be pulled down to AbstractJjtreeNode and made protected.
adangel
left a comment
There was a problem hiding this comment.
Sorry for the late review.
I completely agree to deprecate/remove the "jjt*" methods. I'm not sure yet, which traversal methods we actually should provide with having NodeStream in the future, which provides the same functionality for traversing.
I've added a simple description of the Node API in the wiki: https://github.com/pmd/pmd/wiki/PMD-7.0.0-API#description-of-node-api (based on your very good class comment for Node).
If we add this second way of traversing the AST, then I would right now add directly List<Node> getChildren() instead of having to call two methods (getNumChildren(), getChild(int)) in order to iterate.
In the wiki, I only have the minimum methods. Should we add more methods? Like "getIndexInParent()", "getNextSibling()", "isFirstChild()", "getNthParent(int)", ... there are almost endless possibilities. I guess, the more methods we add, the difficult the API usage becomes?
Very nice!
About the tree traversal methods that are on Node (getParent/getChild/etc): I think we need them to implement NodeStreams. The cool thing about the current node stream implementation is that it works for any Node, using just the four basic primitives getParent/getChild/getNumChildren/getIndexInParent. Having them on the node interface gives a very clear implementation path for someone wanting to make a new Node:
We could imagine a Node interface that strongly relies on NodeStream, ie not exposing those primitives. But then, an implementor of Node will need to implement a FWIW I like the mental model that NodeStream is just free stuff built on top of Node, and not integral to the Node interface. I also think methods like
I would rather make it a
Your suggestion seems very fine to me |
|
More things to say here: I think the methods about XPath should be removed from the interface and handled by an external object. This would decouple our Node -> DOM transformation from node implementations. For now we only map nodes to a DOM element with some attributes. But to support a more complete transformation, some additional methods would be required (eg access to comments, namespace, etc), and adding them directly to the node interface makes it messy. What if we want to change the XPath API, eg change the Attribute class? That's not really the problem of the Node, the AST is still the same. Node instances are meant to be used by eg developers writing Java rules. They don't care about the XPath representation, so won't miss these methods. Also the Attribute objects, if they're created directly by Nodes, cannot know about the DOM they're used in. This is sad, because it would give a simple solution to the problem of reporting usages of deprecated attributes. I imagine we could use something like: interface DomAdapter {
Iterator<Attribute> getAttributes(Node node);
String getElementName(Node node);
}provided by a LanguageVersionHandler. |
The PR deprecates a lot of stuff that should be gone from the interface (and AbstractNode). This will make implementation of the interface much easier, and usage safer.
At the same time I added some methods with non-biased names to the interface. I think since a default implementation is added to AbstractNode too, it should be an acceptable breaking change, and allow user migration to start now.