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: |