Chris@13: attributes = $attributes; Chris@0: } Chris@0: Chris@0: /** Chris@13: * Gets line the node started in (alias of getStartLine). Chris@0: * Chris@13: * @return int Start line (or -1 if not available) Chris@0: */ Chris@13: public function getLine() : int { Chris@13: return $this->attributes['startLine'] ?? -1; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets line the node started in. Chris@0: * Chris@13: * Requires the 'startLine' attribute to be enabled in the lexer (enabled by default). Chris@13: * Chris@13: * @return int Start line (or -1 if not available) Chris@0: */ Chris@13: public function getStartLine() : int { Chris@13: return $this->attributes['startLine'] ?? -1; Chris@0: } Chris@0: Chris@0: /** Chris@13: * Gets the line the node ended in. Chris@0: * Chris@13: * Requires the 'endLine' attribute to be enabled in the lexer (enabled by default). Chris@0: * Chris@13: * @return int End line (or -1 if not available) Chris@0: */ Chris@13: public function getEndLine() : int { Chris@13: return $this->attributes['endLine'] ?? -1; Chris@13: } Chris@13: Chris@13: /** Chris@13: * Gets the token offset of the first token that is part of this node. Chris@13: * Chris@13: * The offset is an index into the array returned by Lexer::getTokens(). Chris@13: * Chris@13: * Requires the 'startTokenPos' attribute to be enabled in the lexer (DISABLED by default). Chris@13: * Chris@13: * @return int Token start position (or -1 if not available) Chris@13: */ Chris@13: public function getStartTokenPos() : int { Chris@13: return $this->attributes['startTokenPos'] ?? -1; Chris@13: } Chris@13: Chris@13: /** Chris@13: * Gets the token offset of the last token that is part of this node. Chris@13: * Chris@13: * The offset is an index into the array returned by Lexer::getTokens(). Chris@13: * Chris@13: * Requires the 'endTokenPos' attribute to be enabled in the lexer (DISABLED by default). Chris@13: * Chris@13: * @return int Token end position (or -1 if not available) Chris@13: */ Chris@13: public function getEndTokenPos() : int { Chris@13: return $this->attributes['endTokenPos'] ?? -1; Chris@13: } Chris@13: Chris@13: /** Chris@13: * Gets the file offset of the first character that is part of this node. Chris@13: * Chris@13: * Requires the 'startFilePos' attribute to be enabled in the lexer (DISABLED by default). Chris@13: * Chris@13: * @return int File start position (or -1 if not available) Chris@13: */ Chris@13: public function getStartFilePos() : int { Chris@13: return $this->attributes['startFilePos'] ?? -1; Chris@13: } Chris@13: Chris@13: /** Chris@13: * Gets the file offset of the last character that is part of this node. Chris@13: * Chris@13: * Requires the 'endFilePos' attribute to be enabled in the lexer (DISABLED by default). Chris@13: * Chris@13: * @return int File end position (or -1 if not available) Chris@13: */ Chris@13: public function getEndFilePos() : int { Chris@13: return $this->attributes['endFilePos'] ?? -1; Chris@13: } Chris@13: Chris@13: /** Chris@13: * Gets all comments directly preceding this node. Chris@13: * Chris@13: * The comments are also available through the "comments" attribute. Chris@13: * Chris@13: * @return Comment[] Chris@13: */ Chris@13: public function getComments() : array { Chris@13: return $this->attributes['comments'] ?? []; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets the doc comment of the node. Chris@0: * Chris@0: * The doc comment has to be the last comment associated with the node. Chris@0: * Chris@0: * @return null|Comment\Doc Doc comment object or null Chris@0: */ Chris@0: public function getDocComment() { Chris@13: $comments = $this->getComments(); Chris@0: if (!$comments) { Chris@0: return null; Chris@0: } Chris@0: Chris@0: $lastComment = $comments[count($comments) - 1]; Chris@0: if (!$lastComment instanceof Comment\Doc) { Chris@0: return null; Chris@0: } Chris@0: Chris@0: return $lastComment; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Sets the doc comment of the node. Chris@0: * Chris@0: * This will either replace an existing doc comment or add it to the comments array. Chris@0: * Chris@0: * @param Comment\Doc $docComment Doc comment to set Chris@0: */ Chris@0: public function setDocComment(Comment\Doc $docComment) { Chris@13: $comments = $this->getComments(); Chris@0: Chris@0: $numComments = count($comments); Chris@0: if ($numComments > 0 && $comments[$numComments - 1] instanceof Comment\Doc) { Chris@0: // Replace existing doc comment Chris@0: $comments[$numComments - 1] = $docComment; Chris@0: } else { Chris@0: // Append new comment Chris@0: $comments[] = $docComment; Chris@0: } Chris@0: Chris@0: $this->setAttribute('comments', $comments); Chris@0: } Chris@0: Chris@13: public function setAttribute(string $key, $value) { Chris@0: $this->attributes[$key] = $value; Chris@0: } Chris@0: Chris@13: public function hasAttribute(string $key) : bool { Chris@0: return array_key_exists($key, $this->attributes); Chris@0: } Chris@0: Chris@13: public function getAttribute(string $key, $default = null) { Chris@17: if (array_key_exists($key, $this->attributes)) { Chris@0: return $this->attributes[$key]; Chris@0: } Chris@17: Chris@17: return $default; Chris@0: } Chris@0: Chris@13: public function getAttributes() : array { Chris@0: return $this->attributes; Chris@0: } Chris@0: Chris@13: public function setAttributes(array $attributes) { Chris@13: $this->attributes = $attributes; Chris@13: } Chris@13: Chris@13: /** Chris@13: * @return array Chris@13: */ Chris@13: public function jsonSerialize() : array { Chris@0: return ['nodeType' => $this->getType()] + get_object_vars($this); Chris@0: } Chris@0: }