Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * PHPUnit
4
 *
5
 * Copyright (c) 2002-2010, Sebastian Bergmann <sb@sebastian-bergmann.de>.
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 *
12
 *   * Redistributions of source code must retain the above copyright
13
 *     notice, this list of conditions and the following disclaimer.
14
 *
15
 *   * Redistributions in binary form must reproduce the above copyright
16
 *     notice, this list of conditions and the following disclaimer in
17
 *     the documentation and/or other materials provided with the
18
 *     distribution.
19
 *
20
 *   * Neither the name of Sebastian Bergmann nor the names of his
21
 *     contributors may be used to endorse or promote products derived
22
 *     from this software without specific prior written permission.
23
 *
24
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35
 * POSSIBILITY OF SUCH DAMAGE.
36
 *
37
 * @category   Testing
38
 * @package    PHPUnit
39
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
40
 * @copyright  2002-2010 Sebastian Bergmann <sb@sebastian-bergmann.de>
41
 * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
42
 * @link       http://www.phpunit.de/
43
 * @since      File available since Release 3.4.0
44
 */
45
 
46
if (!defined('T_NAMESPACE')) {
47
    define('T_NAMESPACE', 377);
48
}
49
 
50
require_once 'PHPUnit/Util/Filter.php';
51
 
52
PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
53
 
54
/**
55
 * File helpers.
56
 *
57
 * @category   Testing
58
 * @package    PHPUnit
59
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
60
 * @copyright  2002-2010 Sebastian Bergmann <sb@sebastian-bergmann.de>
61
 * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
62
 * @version    Release: 3.4.15
63
 * @link       http://www.phpunit.de/
64
 * @since      Class available since Release 3.4.0
65
 */
66
class PHPUnit_Util_File
67
{
68
    /**
69
     * @var array
70
     */
71
    protected static $countCache = array();
72
 
73
    /**
74
     * @var array
75
     */
76
    protected static $classesFunctionsCache = array();
77
 
78
    /**
79
     * Counts LOC, CLOC, and NCLOC for a file.
80
     *
81
     * @param  string $filename
82
     * @return array
83
     */
84
    public static function countLines($filename)
85
    {
86
        if (!isset(self::$countCache[$filename])) {
87
            $buffer = file_get_contents($filename);
88
            $loc    = substr_count($buffer, "\n");
89
            $cloc   = 0;
90
 
91
            foreach (token_get_all($buffer) as $i => $token) {
92
                if (is_string($token)) {
93
                    continue;
94
                }
95
 
96
                list ($token, $value) = $token;
97
 
98
                if ($token == T_COMMENT || $token == T_DOC_COMMENT) {
99
                    $cloc += substr_count($value, "\n") + 1;
100
                }
101
            }
102
 
103
            self::$countCache[$filename] = array(
104
              'loc' => $loc, 'cloc' => $cloc, 'ncloc' => $loc - $cloc
105
            );
106
        }
107
 
108
        return self::$countCache[$filename];
109
    }
110
 
111
    /**
112
     * Returns information on the classes declared in a sourcefile.
113
     *
114
     * @param  string $filename
115
     * @return array
116
     */
117
    public static function getClassesInFile($filename)
118
    {
119
        if (!isset(self::$classesFunctionsCache[$filename])) {
120
            self::parseFile($filename);
121
        }
122
 
123
        return self::$classesFunctionsCache[$filename]['classes'];
124
    }
125
 
126
    /**
127
     * Returns information on the functions declared in a sourcefile.
128
     *
129
     * @param  string $filename
130
     * @return array
131
     */
132
    public static function getFunctionsInFile($filename)
133
    {
134
        if (!isset(self::$classesFunctionsCache[$filename])) {
135
            self::parseFile($filename);
136
        }
137
 
138
        return self::$classesFunctionsCache[$filename]['functions'];
139
    }
140
 
141
    /**
142
     * Parses a file for class, method, and function information.
143
     *
144
     * @param string $filename
145
     */
146
    protected static function parseFile($filename)
147
    {
148
        self::$classesFunctionsCache[$filename] = array(
149
          'classes' => array(), 'functions' => array()
150
        );
151
 
152
        $tokens                     = token_get_all(
153
                                        file_get_contents($filename)
154
                                      );
155
        $numTokens                  = count($tokens);
156
        $blocks                     = array();
157
        $line                       = 1;
158
        $currentBlock               = FALSE;
159
        $currentNamespace           = FALSE;
160
        $currentClass               = FALSE;
161
        $currentFunction            = FALSE;
162
        $currentFunctionStartLine   = FALSE;
163
        $currentFunctionTokens      = array();
164
        $currentDocComment          = FALSE;
165
        $currentSignature           = FALSE;
166
        $currentSignatureStartToken = FALSE;
167
 
168
        for ($i = 0; $i < $numTokens; $i++) {
169
            if ($currentFunction !== FALSE) {
170
                $currentFunctionTokens[] = $tokens[$i];
171
            }
172
 
173
            if (is_string($tokens[$i])) {
174
                if ($tokens[$i] == '{') {
175
                    if ($currentBlock == T_CLASS) {
176
                        $block = $currentClass;
177
                    }
178
 
179
                    else if ($currentBlock == T_FUNCTION) {
180
                        $currentSignature = '';
181
 
182
                        for ($j = $currentSignatureStartToken; $j < $i; $j++) {
183
                            if (is_string($tokens[$j])) {
184
                                $currentSignature .= $tokens[$j];
185
                            } else {
186
                                $currentSignature .= $tokens[$j][1];
187
                            }
188
                        }
189
 
190
                        $currentSignature = trim($currentSignature);
191
 
192
                        $block                      = $currentFunction;
193
                        $currentSignatureStartToken = FALSE;
194
                    }
195
 
196
                    else {
197
                        $block = FALSE;
198
                    }
199
 
200
                    array_push($blocks, $block);
201
 
202
                    $currentBlock = FALSE;
203
                }
204
 
205
                else if ($tokens[$i] == '}') {
206
                    $block = array_pop($blocks);
207
 
208
                    if ($block !== FALSE && $block !== NULL) {
209
                        if ($block == $currentFunction) {
210
                            if ($currentDocComment !== FALSE) {
211
                                $docComment        = $currentDocComment;
212
                                $currentDocComment = FALSE;
213
                            } else {
214
                                $docComment = '';
215
                            }
216
 
217
                            $tmp = array(
218
                              'docComment' => $docComment,
219
                              'signature'  => $currentSignature,
220
                              'startLine'  => $currentFunctionStartLine,
221
                              'endLine'    => $line,
222
                              'tokens'     => $currentFunctionTokens
223
                            );
224
 
225
                            if ($currentClass === FALSE) {
226
                                self::$classesFunctionsCache[$filename]['functions'][$currentFunction] = $tmp;
227
                            } else {
228
                                self::$classesFunctionsCache[$filename]['classes'][$currentClass]['methods'][$currentFunction] = $tmp;
229
                            }
230
 
231
                            $currentFunction          = FALSE;
232
                            $currentFunctionStartLine = FALSE;
233
                            $currentFunctionTokens    = array();
234
                            $currentSignature         = FALSE;
235
                        }
236
 
237
                        else if ($block == $currentClass) {
238
                            self::$classesFunctionsCache[$filename]['classes'][$currentClass]['endLine'] = $line;
239
 
240
                            $currentClass          = FALSE;
241
                            $currentClassStartLine = FALSE;
242
                        }
243
                    }
244
                }
245
 
246
                continue;
247
            }
248
 
249
            switch ($tokens[$i][0]) {
250
                case T_NAMESPACE: {
251
                    $currentNamespace = $tokens[$i+2][1];
252
 
253
                    for ($j = $i+3; $j < $numTokens; $j += 2) {
254
                        if ($tokens[$j][0] == T_NS_SEPARATOR) {
255
                            $currentNamespace .= '\\' . $tokens[$j+1][1];
256
                        } else {
257
                            break;
258
                        }
259
                    }
260
                }
261
                break;
262
 
263
                case T_CURLY_OPEN: {
264
                    $currentBlock = T_CURLY_OPEN;
265
                    array_push($blocks, $currentBlock);
266
                }
267
                break;
268
 
269
                case T_DOLLAR_OPEN_CURLY_BRACES: {
270
                    $currentBlock = T_DOLLAR_OPEN_CURLY_BRACES;
271
                    array_push($blocks, $currentBlock);
272
                }
273
                break;
274
 
275
                case T_CLASS: {
276
                    $currentBlock = T_CLASS;
277
 
278
                    if ($currentNamespace === FALSE) {
279
                        $currentClass = $tokens[$i+2][1];
280
                    } else {
281
                        $currentClass = $currentNamespace . '\\' .
282
                                        $tokens[$i+2][1];
283
                    }
284
 
285
                    if ($currentDocComment !== FALSE) {
286
                        $docComment        = $currentDocComment;
287
                        $currentDocComment = FALSE;
288
                    } else {
289
                        $docComment = '';
290
                    }
291
 
292
                    self::$classesFunctionsCache[$filename]['classes'][$currentClass] = array(
293
                      'methods'    => array(),
294
                      'docComment' => $docComment,
295
                      'startLine'  => $line
296
                    );
297
                }
298
                break;
299
 
300
                case T_FUNCTION: {
301
                    if (!((is_array($tokens[$i+2]) &&
302
                          $tokens[$i+2][0] == T_STRING) ||
303
                         (is_string($tokens[$i+2]) &&
304
                          $tokens[$i+2] == '&' &&
305
                          is_array($tokens[$i+3]) &&
306
                          $tokens[$i+3][0] == T_STRING))) {
307
                        continue;
308
                    }
309
 
310
                    $currentBlock             = T_FUNCTION;
311
                    $currentFunctionStartLine = $line;
312
 
313
                    $done                       = FALSE;
314
                    $currentSignatureStartToken = $i - 1;
315
 
316
                    do {
317
                        switch ($tokens[$currentSignatureStartToken][0]) {
318
                            case T_ABSTRACT:
319
                            case T_FINAL:
320
                            case T_PRIVATE:
321
                            case T_PUBLIC:
322
                            case T_PROTECTED:
323
                            case T_STATIC:
324
                            case T_WHITESPACE: {
325
                                $currentSignatureStartToken--;
326
                            }
327
                            break;
328
 
329
                            default: {
330
                                $currentSignatureStartToken++;
331
                                $done = TRUE;
332
                            }
333
                        }
334
                    }
335
                    while (!$done);
336
 
337
                    if (isset($tokens[$i+2][1])) {
338
                        $functionName = $tokens[$i+2][1];
339
                    }
340
 
341
                    else if (isset($tokens[$i+3][1])) {
342
                        $functionName = $tokens[$i+3][1];
343
                    }
344
 
345
                    if ($currentNamespace === FALSE) {
346
                        $currentFunction = $functionName;
347
                    } else {
348
                        $currentFunction = $currentNamespace . '\\' .
349
                                           $functionName;
350
                    }
351
                }
352
                break;
353
 
354
                case T_DOC_COMMENT: {
355
                    $currentDocComment = $tokens[$i][1];
356
                }
357
                break;
358
            }
359
 
360
            $line += substr_count($tokens[$i][1], "\n");
361
        }
362
    }
363
}
364
?>