comparison vendor/nikic/php-parser/test/PhpParser/PrettyPrinterTest.php @ 13:5fb285c0d0e3

Update Drupal core to 8.4.7 via Composer. Security update; I *think* we've been lucky to get away with this so far, as we don't support self-registration which seems to be used by the so-called "drupalgeddon 2" attack that 8.4.5 was vulnerable to.
author Chris Cannam
date Mon, 23 Apr 2018 09:33:26 +0100
parents 4c8ae668cc8c
children c2387f117808
comparison
equal deleted inserted replaced
12:7a779792577d 13:5fb285c0d0e3
1 <?php 1 <?php declare(strict_types=1);
2 2
3 namespace PhpParser; 3 namespace PhpParser;
4 4
5 use PhpParser\Comment;
6 use PhpParser\Node\Expr; 5 use PhpParser\Node\Expr;
7 use PhpParser\Node\Name; 6 use PhpParser\Node\Name;
8 use PhpParser\Node\Scalar\DNumber; 7 use PhpParser\Node\Scalar\DNumber;
9 use PhpParser\Node\Scalar\Encapsed; 8 use PhpParser\Node\Scalar\Encapsed;
10 use PhpParser\Node\Scalar\EncapsedStringPart; 9 use PhpParser\Node\Scalar\EncapsedStringPart;
44 } 43 }
45 44
46 if ('php5' === $version) { 45 if ('php5' === $version) {
47 $this->assertSame($expected, $output5, $name); 46 $this->assertSame($expected, $output5, $name);
48 $this->assertNotSame($expected, $output7, $name); 47 $this->assertNotSame($expected, $output7, $name);
49 } else if ('php7' === $version) { 48 } elseif ('php7' === $version) {
50 $this->assertSame($expected, $output7, $name); 49 $this->assertSame($expected, $output7, $name);
51 $this->assertNotSame($expected, $output5, $name); 50 $this->assertNotSame($expected, $output5, $name);
52 } else { 51 } else {
53 $this->assertSame($expected, $output5, $name); 52 $this->assertSame($expected, $output5, $name);
54 $this->assertSame($expected, $output7, $name); 53 $this->assertSame($expected, $output7, $name);
55 } 54 }
56 } 55 }
57 56
58 /** 57 /**
59 * @dataProvider provideTestPrettyPrint 58 * @dataProvider provideTestPrettyPrint
60 * @covers PhpParser\PrettyPrinter\Standard<extended> 59 * @covers \PhpParser\PrettyPrinter\Standard<extended>
61 */ 60 */
62 public function testPrettyPrint($name, $code, $expected, $mode) { 61 public function testPrettyPrint($name, $code, $expected, $mode) {
63 $this->doTestPrettyPrintMethod('prettyPrint', $name, $code, $expected, $mode); 62 $this->doTestPrettyPrintMethod('prettyPrint', $name, $code, $expected, $mode);
64 } 63 }
65 64
66 /** 65 /**
67 * @dataProvider provideTestPrettyPrintFile 66 * @dataProvider provideTestPrettyPrintFile
68 * @covers PhpParser\PrettyPrinter\Standard<extended> 67 * @covers \PhpParser\PrettyPrinter\Standard<extended>
69 */ 68 */
70 public function testPrettyPrintFile($name, $code, $expected, $mode) { 69 public function testPrettyPrintFile($name, $code, $expected, $mode) {
71 $this->doTestPrettyPrintMethod('prettyPrintFile', $name, $code, $expected, $mode); 70 $this->doTestPrettyPrintMethod('prettyPrintFile', $name, $code, $expected, $mode);
72 } 71 }
73 72
85 new Expr\BinaryOp\Plus(new Expr\Variable('a'), new Expr\Variable('b')), 84 new Expr\BinaryOp\Plus(new Expr\Variable('a'), new Expr\Variable('b')),
86 new Expr\Variable('c') 85 new Expr\Variable('c')
87 ); 86 );
88 $this->assertEquals('($a + $b) * $c', $prettyPrinter->prettyPrintExpr($expr)); 87 $this->assertEquals('($a + $b) * $c', $prettyPrinter->prettyPrintExpr($expr));
89 88
90 $expr = new Expr\Closure(array( 89 $expr = new Expr\Closure([
91 'stmts' => array(new Stmt\Return_(new String_("a\nb"))) 90 'stmts' => [new Stmt\Return_(new String_("a\nb"))]
92 )); 91 ]);
93 $this->assertEquals("function () {\n return 'a\nb';\n}", $prettyPrinter->prettyPrintExpr($expr)); 92 $this->assertEquals("function () {\n return 'a\nb';\n}", $prettyPrinter->prettyPrintExpr($expr));
94 } 93 }
95 94
96 public function testCommentBeforeInlineHTML() { 95 public function testCommentBeforeInlineHTML() {
97 $prettyPrinter = new PrettyPrinter\Standard; 96 $prettyPrinter = new PrettyPrinter\Standard;
100 $expected = "<?php\n\n/**\n * This is a comment\n */\n?>\nHello World!"; 99 $expected = "<?php\n\n/**\n * This is a comment\n */\n?>\nHello World!";
101 $this->assertSame($expected, $prettyPrinter->prettyPrintFile($stmts)); 100 $this->assertSame($expected, $prettyPrinter->prettyPrintFile($stmts));
102 } 101 }
103 102
104 private function parseModeLine($modeLine) { 103 private function parseModeLine($modeLine) {
105 $parts = explode(' ', $modeLine, 2); 104 $parts = explode(' ', (string) $modeLine, 2);
106 $version = isset($parts[0]) ? $parts[0] : 'both'; 105 $version = $parts[0] ?? 'both';
107 $options = isset($parts[1]) ? json_decode($parts[1], true) : []; 106 $options = isset($parts[1]) ? json_decode($parts[1], true) : [];
108 return [$version, $options]; 107 return [$version, $options];
109 } 108 }
110 109
111 public function testArraySyntaxDefault() { 110 public function testArraySyntaxDefault() {
188 /** 187 /**
189 * @expectedException \LogicException 188 * @expectedException \LogicException
190 * @expectedExceptionMessage Cannot pretty-print AST with Error nodes 189 * @expectedExceptionMessage Cannot pretty-print AST with Error nodes
191 */ 190 */
192 public function testPrettyPrintWithError() { 191 public function testPrettyPrintWithError() {
193 $stmts = [new Expr\PropertyFetch(new Expr\Variable('a'), new Expr\Error())]; 192 $stmts = [new Stmt\Expression(
193 new Expr\PropertyFetch(new Expr\Variable('a'), new Expr\Error())
194 )];
194 $prettyPrinter = new PrettyPrinter\Standard; 195 $prettyPrinter = new PrettyPrinter\Standard;
195 $prettyPrinter->prettyPrint($stmts); 196 $prettyPrinter->prettyPrint($stmts);
196 } 197 }
197 198
198 /** 199 /**
199 * @expectedException \LogicException 200 * @expectedException \LogicException
200 * @expectedExceptionMessage Cannot pretty-print AST with Error nodes 201 * @expectedExceptionMessage Cannot pretty-print AST with Error nodes
201 */ 202 */
202 public function testPrettyPrintWithErrorInClassConstFetch() { 203 public function testPrettyPrintWithErrorInClassConstFetch() {
203 $stmts = [new Expr\ClassConstFetch(new Name('Foo'), new Expr\Error())]; 204 $stmts = [new Stmt\Expression(
205 new Expr\ClassConstFetch(new Name('Foo'), new Expr\Error())
206 )];
204 $prettyPrinter = new PrettyPrinter\Standard; 207 $prettyPrinter = new PrettyPrinter\Standard;
205 $prettyPrinter->prettyPrint($stmts); 208 $prettyPrinter->prettyPrint($stmts);
206 } 209 }
210
211 /**
212 * @dataProvider provideTestFormatPreservingPrint
213 * @covers \PhpParser\PrettyPrinter\Standard<extended>
214 */
215 public function testFormatPreservingPrint($name, $code, $modification, $expected, $modeLine) {
216 $lexer = new Lexer\Emulative([
217 'usedAttributes' => [
218 'comments',
219 'startLine', 'endLine',
220 'startTokenPos', 'endTokenPos',
221 ],
222 ]);
223
224 $parser = new Parser\Php7($lexer);
225 $traverser = new NodeTraverser();
226 $traverser->addVisitor(new NodeVisitor\CloningVisitor());
227
228 $printer = new PrettyPrinter\Standard();
229
230 $oldStmts = $parser->parse($code);
231 $oldTokens = $lexer->getTokens();
232
233 $newStmts = $traverser->traverse($oldStmts);
234
235 /** @var callable $fn */
236 eval(<<<CODE
237 use PhpParser\Comment;
238 use PhpParser\Node;
239 use PhpParser\Node\Expr;
240 use PhpParser\Node\Scalar;
241 use PhpParser\Node\Stmt;
242 \$fn = function(&\$stmts) { $modification };
243 CODE
244 );
245 $fn($newStmts);
246
247 $newCode = $printer->printFormatPreserving($newStmts, $oldStmts, $oldTokens);
248 $this->assertSame(canonicalize($expected), canonicalize($newCode), $name);
249 }
250
251 public function provideTestFormatPreservingPrint() {
252 return $this->getTests(__DIR__ . '/../code/formatPreservation', 'test', 3);
253 }
254
255 /**
256 * @dataProvider provideTestRoundTripPrint
257 * @covers \PhpParser\PrettyPrinter\Standard<extended>
258 */
259 public function testRoundTripPrint($name, $code, $expected, $modeLine) {
260 /**
261 * This test makes sure that the format-preserving pretty printer round-trips for all
262 * the pretty printer tests (i.e. returns the input if no changes occurred).
263 */
264
265 list($version) = $this->parseModeLine($modeLine);
266
267 $lexer = new Lexer\Emulative([
268 'usedAttributes' => [
269 'comments',
270 'startLine', 'endLine',
271 'startTokenPos', 'endTokenPos',
272 ],
273 ]);
274
275 $parserClass = $version === 'php5' ? Parser\Php5::class : Parser\Php7::class;
276 /** @var Parser $parser */
277 $parser = new $parserClass($lexer);
278
279 $traverser = new NodeTraverser();
280 $traverser->addVisitor(new NodeVisitor\CloningVisitor());
281
282 $printer = new PrettyPrinter\Standard();
283
284 try {
285 $oldStmts = $parser->parse($code);
286 } catch (Error $e) {
287 // Can't do a format-preserving print on a file with errors
288 return;
289 }
290
291 $oldTokens = $lexer->getTokens();
292
293 $newStmts = $traverser->traverse($oldStmts);
294
295 $newCode = $printer->printFormatPreserving($newStmts, $oldStmts, $oldTokens);
296 $this->assertSame(canonicalize($code), canonicalize($newCode), $name);
297 }
298
299 public function provideTestRoundTripPrint() {
300 return array_merge(
301 $this->getTests(__DIR__ . '/../code/prettyPrinter', 'test'),
302 $this->getTests(__DIR__ . '/../code/parser', 'test')
303 );
304 }
207 } 305 }