diff --git a/README.md b/README.md index c64a2d80..a915c046 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ Documentation 2. [Usage of basic components](doc/2_Usage_of_basic_components.markdown) 3. [Other node tree representations](doc/3_Other_node_tree_representations.markdown) 4. [Code generation](doc/4_Code_generation.markdown) + 5. [Frequently asked questions](doc/5_FAQ.markdown) Component documentation: diff --git a/doc/5_FAQ.markdown b/doc/5_FAQ.markdown new file mode 100644 index 00000000..013f68b4 --- /dev/null +++ b/doc/5_FAQ.markdown @@ -0,0 +1,68 @@ +Frequently Asked Questions +========================== + + * [How can the parent of a node be obtained?](#how-can-the-parent-of-a-node-be-obtained-) + * [How can the next/previous sibling of a node be obtained?](#how-can-the-next-previous-sibling-of-a-node-be-obtained-) + +How can the parent of a node be obtained? +----- + +The AST does not store parent nodes by default. However, it is easy to add a custom parent node +attribute using a custom node visitor: + +```php +use PhpParser\Node; +use PhpParser\NodeVisitorAbstract; + +class ParentConnector extends NodeVisitorAbstract { + private $stack; + public function beginTraverse(array $nodes) { + $this->stack = []; + } + public function enterNode(Node $node) { + if (!empty($this->stack)) { + $node->setAttribute('parent', $this->stack[count($this->stack)-1]); + } + $this->stack[] = $node; + } + public function leaveNode(Node $node) { + array_pop($this->stack); + } +} +``` + +After running this visitor, the parent node can be obtained through `$node->getAttribute('parent')`. + +How can the next/previous sibling of a node be obtained? +----- + +Again, siblings are not stored by default, but the visitor from the previous entry can be easily +extended to store the previous / next node with a common parent as well: + +```php +use PhpParser\Node; +use PhpParser\NodeVisitorAbstract; + +class NodeConnector extends NodeVisitorAbstract { + private $stack; + private $prev; + public function beginTraverse(array $nodes) { + $this->stack = []; + $this->prev = null; + } + public function enterNode(Node $node) { + if (!empty($this->stack)) { + $node->setAttribute('parent', $this->stack[count($this->stack)-1]); + } + if ($this->prev && $this->prev->getAttribute('parent') == $node->getAttribute('parent')) { + $node->setAttribute('prev', $this->prev); + $this->prev->setAttribute('next', $node); + } + $this->stack[] = $node; + } + public function leaveNode(Node $node) { + $this->prev = $node; + array_pop($this->stack); + } +} +``` \ No newline at end of file