1: <?php declare(strict_types=1);
2:
3: namespace PhpParser;
4:
5: abstract class NodeAbstract implements Node, \JsonSerializable
6: {
7: protected $attributes;
8:
9: /**
10: * Creates a Node.
11: *
12: * @param array $attributes Array of attributes
13: */
14: public function __construct(array $attributes = []) {
15: $this->attributes = $attributes;
16: }
17:
18: /**
19: * Gets line the node started in (alias of getStartLine).
20: *
21: * @return int Start line (or -1 if not available)
22: */
23: public function getLine() : int {
24: return $this->attributes['startLine'] ?? -1;
25: }
26:
27: /**
28: * Gets line the node started in.
29: *
30: * Requires the 'startLine' attribute to be enabled in the lexer (enabled by default).
31: *
32: * @return int Start line (or -1 if not available)
33: */
34: public function getStartLine() : int {
35: return $this->attributes['startLine'] ?? -1;
36: }
37:
38: /**
39: * Gets the line the node ended in.
40: *
41: * Requires the 'endLine' attribute to be enabled in the lexer (enabled by default).
42: *
43: * @return int End line (or -1 if not available)
44: */
45: public function getEndLine() : int {
46: return $this->attributes['endLine'] ?? -1;
47: }
48:
49: /**
50: * Gets the token offset of the first token that is part of this node.
51: *
52: * The offset is an index into the array returned by Lexer::getTokens().
53: *
54: * Requires the 'startTokenPos' attribute to be enabled in the lexer (DISABLED by default).
55: *
56: * @return int Token start position (or -1 if not available)
57: */
58: public function getStartTokenPos() : int {
59: return $this->attributes['startTokenPos'] ?? -1;
60: }
61:
62: /**
63: * Gets the token offset of the last token that is part of this node.
64: *
65: * The offset is an index into the array returned by Lexer::getTokens().
66: *
67: * Requires the 'endTokenPos' attribute to be enabled in the lexer (DISABLED by default).
68: *
69: * @return int Token end position (or -1 if not available)
70: */
71: public function getEndTokenPos() : int {
72: return $this->attributes['endTokenPos'] ?? -1;
73: }
74:
75: /**
76: * Gets the file offset of the first character that is part of this node.
77: *
78: * Requires the 'startFilePos' attribute to be enabled in the lexer (DISABLED by default).
79: *
80: * @return int File start position (or -1 if not available)
81: */
82: public function getStartFilePos() : int {
83: return $this->attributes['startFilePos'] ?? -1;
84: }
85:
86: /**
87: * Gets the file offset of the last character that is part of this node.
88: *
89: * Requires the 'endFilePos' attribute to be enabled in the lexer (DISABLED by default).
90: *
91: * @return int File end position (or -1 if not available)
92: */
93: public function getEndFilePos() : int {
94: return $this->attributes['endFilePos'] ?? -1;
95: }
96:
97: /**
98: * Gets all comments directly preceding this node.
99: *
100: * The comments are also available through the "comments" attribute.
101: *
102: * @return Comment[]
103: */
104: public function getComments() : array {
105: return $this->attributes['comments'] ?? [];
106: }
107:
108: /**
109: * Gets the doc comment of the node.
110: *
111: * @return null|Comment\Doc Doc comment object or null
112: */
113: public function getDocComment() {
114: $comments = $this->getComments();
115: for ($i = count($comments) - 1; $i >= 0; $i--) {
116: $comment = $comments[$i];
117: if ($comment instanceof Comment\Doc) {
118: return $comment;
119: }
120: }
121:
122: return null;
123: }
124:
125: /**
126: * Sets the doc comment of the node.
127: *
128: * This will either replace an existing doc comment or add it to the comments array.
129: *
130: * @param Comment\Doc $docComment Doc comment to set
131: */
132: public function setDocComment(Comment\Doc $docComment) {
133: $comments = $this->getComments();
134: for ($i = count($comments) - 1; $i >= 0; $i--) {
135: if ($comments[$i] instanceof Comment\Doc) {
136: // Replace existing doc comment.
137: $comments[$i] = $docComment;
138: $this->setAttribute('comments', $comments);
139: return;
140: }
141: }
142:
143: // Append new doc comment.
144: $comments[] = $docComment;
145: $this->setAttribute('comments', $comments);
146: }
147:
148: public function setAttribute(string $key, $value) {
149: $this->attributes[$key] = $value;
150: }
151:
152: public function hasAttribute(string $key) : bool {
153: return array_key_exists($key, $this->attributes);
154: }
155:
156: public function getAttribute(string $key, $default = null) {
157: if (array_key_exists($key, $this->attributes)) {
158: return $this->attributes[$key];
159: }
160:
161: return $default;
162: }
163:
164: public function getAttributes() : array {
165: return $this->attributes;
166: }
167:
168: public function setAttributes(array $attributes) {
169: $this->attributes = $attributes;
170: }
171:
172: /**
173: * @return array
174: */
175: public function jsonSerialize() : array {
176: return ['nodeType' => $this->getType()] + get_object_vars($this);
177: }
178: }
179: