Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php declare(strict_types=1);
2
 
3
namespace PhpParser;
4
 
5
class Comment implements \JsonSerializable
6
{
7
    protected $text;
8
    protected $startLine;
9
    protected $startFilePos;
10
    protected $startTokenPos;
11
    protected $endLine;
12
    protected $endFilePos;
13
    protected $endTokenPos;
14
 
15
    /**
16
     * Constructs a comment node.
17
     *
18
     * @param string $text          Comment text (including comment delimiters like /*)
19
     * @param int    $startLine     Line number the comment started on
20
     * @param int    $startFilePos  File offset the comment started on
21
     * @param int    $startTokenPos Token offset the comment started on
22
     */
23
    public function __construct(
24
        string $text,
25
        int $startLine = -1, int $startFilePos = -1, int $startTokenPos = -1,
26
        int $endLine = -1, int $endFilePos = -1, int $endTokenPos = -1
27
    ) {
28
        $this->text = $text;
29
        $this->startLine = $startLine;
30
        $this->startFilePos = $startFilePos;
31
        $this->startTokenPos = $startTokenPos;
32
        $this->endLine = $endLine;
33
        $this->endFilePos = $endFilePos;
34
        $this->endTokenPos = $endTokenPos;
35
    }
36
 
37
    /**
38
     * Gets the comment text.
39
     *
40
     * @return string The comment text (including comment delimiters like /*)
41
     */
42
    public function getText() : string {
43
        return $this->text;
44
    }
45
 
46
    /**
47
     * Gets the line number the comment started on.
48
     *
49
     * @return int Line number (or -1 if not available)
50
     */
51
    public function getStartLine() : int {
52
        return $this->startLine;
53
    }
54
 
55
    /**
56
     * Gets the file offset the comment started on.
57
     *
58
     * @return int File offset (or -1 if not available)
59
     */
60
    public function getStartFilePos() : int {
61
        return $this->startFilePos;
62
    }
63
 
64
    /**
65
     * Gets the token offset the comment started on.
66
     *
67
     * @return int Token offset (or -1 if not available)
68
     */
69
    public function getStartTokenPos() : int {
70
        return $this->startTokenPos;
71
    }
72
 
73
    /**
74
     * Gets the line number the comment ends on.
75
     *
76
     * @return int Line number (or -1 if not available)
77
     */
78
    public function getEndLine() : int {
79
        return $this->endLine;
80
    }
81
 
82
    /**
83
     * Gets the file offset the comment ends on.
84
     *
85
     * @return int File offset (or -1 if not available)
86
     */
87
    public function getEndFilePos() : int {
88
        return $this->endFilePos;
89
    }
90
 
91
    /**
92
     * Gets the token offset the comment ends on.
93
     *
94
     * @return int Token offset (or -1 if not available)
95
     */
96
    public function getEndTokenPos() : int {
97
        return $this->endTokenPos;
98
    }
99
 
100
    /**
101
     * Gets the line number the comment started on.
102
     *
103
     * @deprecated Use getStartLine() instead
104
     *
105
     * @return int Line number
106
     */
107
    public function getLine() : int {
108
        return $this->startLine;
109
    }
110
 
111
    /**
112
     * Gets the file offset the comment started on.
113
     *
114
     * @deprecated Use getStartFilePos() instead
115
     *
116
     * @return int File offset
117
     */
118
    public function getFilePos() : int {
119
        return $this->startFilePos;
120
    }
121
 
122
    /**
123
     * Gets the token offset the comment started on.
124
     *
125
     * @deprecated Use getStartTokenPos() instead
126
     *
127
     * @return int Token offset
128
     */
129
    public function getTokenPos() : int {
130
        return $this->startTokenPos;
131
    }
132
 
133
    /**
134
     * Gets the comment text.
135
     *
136
     * @return string The comment text (including comment delimiters like /*)
137
     */
138
    public function __toString() : string {
139
        return $this->text;
140
    }
141
 
142
    /**
143
     * Gets the reformatted comment text.
144
     *
145
     * "Reformatted" here means that we try to clean up the whitespace at the
146
     * starts of the lines. This is necessary because we receive the comments
147
     * without trailing whitespace on the first line, but with trailing whitespace
148
     * on all subsequent lines.
149
     *
150
     * @return mixed|string
151
     */
152
    public function getReformattedText() {
153
        $text = trim($this->text);
154
        $newlinePos = strpos($text, "\n");
155
        if (false === $newlinePos) {
156
            // Single line comments don't need further processing
157
            return $text;
158
        } elseif (preg_match('((*BSR_ANYCRLF)(*ANYCRLF)^.*(?:\R\s+\*.*)+$)', $text)) {
159
            // Multi line comment of the type
160
            //
161
            //     /*
162
            //      * Some text.
163
            //      * Some more text.
164
            //      */
165
            //
166
            // is handled by replacing the whitespace sequences before the * by a single space
167
            return preg_replace('(^\s+\*)m', ' *', $this->text);
168
        } elseif (preg_match('(^/\*\*?\s*[\r\n])', $text) && preg_match('(\n(\s*)\*/$)', $text, $matches)) {
169
            // Multi line comment of the type
170
            //
171
            //    /*
172
            //        Some text.
173
            //        Some more text.
174
            //    */
175
            //
176
            // is handled by removing the whitespace sequence on the line before the closing
177
            // */ on all lines. So if the last line is "    */", then "    " is removed at the
178
            // start of all lines.
179
            return preg_replace('(^' . preg_quote($matches[1]) . ')m', '', $text);
180
        } elseif (preg_match('(^/\*\*?\s*(?!\s))', $text, $matches)) {
181
            // Multi line comment of the type
182
            //
183
            //     /* Some text.
184
            //        Some more text.
185
            //          Indented text.
186
            //        Even more text. */
187
            //
188
            // is handled by removing the difference between the shortest whitespace prefix on all
189
            // lines and the length of the "/* " opening sequence.
190
            $prefixLen = $this->getShortestWhitespacePrefixLen(substr($text, $newlinePos + 1));
191
            $removeLen = $prefixLen - strlen($matches[0]);
192
            return preg_replace('(^\s{' . $removeLen . '})m', '', $text);
193
        }
194
 
195
        // No idea how to format this comment, so simply return as is
196
        return $text;
197
    }
198
 
199
    /**
200
     * Get length of shortest whitespace prefix (at the start of a line).
201
     *
202
     * If there is a line with no prefix whitespace, 0 is a valid return value.
203
     *
204
     * @param string $str String to check
205
     * @return int Length in characters. Tabs count as single characters.
206
     */
207
    private function getShortestWhitespacePrefixLen(string $str) : int {
208
        $lines = explode("\n", $str);
209
        $shortestPrefixLen = \INF;
210
        foreach ($lines as $line) {
211
            preg_match('(^\s*)', $line, $matches);
212
            $prefixLen = strlen($matches[0]);
213
            if ($prefixLen < $shortestPrefixLen) {
214
                $shortestPrefixLen = $prefixLen;
215
            }
216
        }
217
        return $shortestPrefixLen;
218
    }
219
 
220
    /**
221
     * @return       array
222
     * @psalm-return array{nodeType:string, text:mixed, line:mixed, filePos:mixed}
223
     */
224
    public function jsonSerialize() : array {
225
        // Technically not a node, but we make it look like one anyway
226
        $type = $this instanceof Comment\Doc ? 'Comment_Doc' : 'Comment';
227
        return [
228
            'nodeType' => $type,
229
            'text' => $this->text,
230
            // TODO: Rename these to include "start".
231
            'line' => $this->startLine,
232
            'filePos' => $this->startFilePos,
233
            'tokenPos' => $this->startTokenPos,
234
            'endLine' => $this->endLine,
235
            'endFilePos' => $this->endFilePos,
236
            'endTokenPos' => $this->endTokenPos,
237
        ];
238
    }
239
}