1# Test file from PPIx::Utilities::Node 2 3use strict; 4use warnings; 5 6use Data::Dumper qw< >; 7use PPI::Document qw< >; 8use PPI::Dumper qw< >; 9use PPIx::Utils::Traversal qw< split_ppi_node_by_namespace >; 10 11use Test::More; 12 13my $DUMP_INDENT = 4; 14 15{ 16 my $source = <<'END_SOURCE'; 17package Foo; 18$x = 1; 19while (1) { $y = 2 } 20until (1) { $z = 3 } 21if (1) { $w = 4 } 22unless (1) { $v = 5 } 23for (1) { $u = 6 } 24foreach (1) { $t = 7 } 25given (1) { $s = 8 } 26when (1) { $r = 9 } 27END_SOURCE 28 29 my %expected = ( 30 Foo => [ <<'END_EXPECTED' ], 31 PPI::Document 32 PPI::Statement::Package 33[ 1, 1, 1 ] PPI::Token::Word 'package' 34[ 1, 8, 8 ] PPI::Token::Whitespace ' ' 35[ 1, 9, 9 ] PPI::Token::Word 'Foo' 36[ 1, 12, 12 ] PPI::Token::Structure ';' 37[ 1, 13, 13 ] PPI::Token::Whitespace '\n' 38 PPI::Statement 39[ 2, 1, 1 ] PPI::Token::Symbol '$x' 40[ 2, 3, 3 ] PPI::Token::Whitespace ' ' 41[ 2, 4, 4 ] PPI::Token::Operator '=' 42[ 2, 5, 5 ] PPI::Token::Whitespace ' ' 43[ 2, 6, 6 ] PPI::Token::Number '1' 44[ 2, 7, 7 ] PPI::Token::Structure ';' 45[ 2, 8, 8 ] PPI::Token::Whitespace '\n' 46 PPI::Statement::Compound 47[ 3, 1, 1 ] PPI::Token::Word 'while' 48[ 3, 6, 6 ] PPI::Token::Whitespace ' ' 49 PPI::Structure::Condition ( ... ) 50 PPI::Statement::Expression 51[ 3, 8, 8 ] PPI::Token::Number '1' 52[ 3, 10, 10 ] PPI::Token::Whitespace ' ' 53 PPI::Structure::Block { ... } 54[ 3, 12, 12 ] PPI::Token::Whitespace ' ' 55 PPI::Statement 56[ 3, 13, 13 ] PPI::Token::Symbol '$y' 57[ 3, 15, 15 ] PPI::Token::Whitespace ' ' 58[ 3, 16, 16 ] PPI::Token::Operator '=' 59[ 3, 17, 17 ] PPI::Token::Whitespace ' ' 60[ 3, 18, 18 ] PPI::Token::Number '2' 61[ 3, 19, 19 ] PPI::Token::Whitespace ' ' 62[ 3, 21, 21 ] PPI::Token::Whitespace '\n' 63 PPI::Statement::Compound 64[ 4, 1, 1 ] PPI::Token::Word 'until' 65[ 4, 6, 6 ] PPI::Token::Whitespace ' ' 66 PPI::Structure::Condition ( ... ) 67 PPI::Statement::Expression 68[ 4, 8, 8 ] PPI::Token::Number '1' 69[ 4, 10, 10 ] PPI::Token::Whitespace ' ' 70 PPI::Structure::Block { ... } 71[ 4, 12, 12 ] PPI::Token::Whitespace ' ' 72 PPI::Statement 73[ 4, 13, 13 ] PPI::Token::Symbol '$z' 74[ 4, 15, 15 ] PPI::Token::Whitespace ' ' 75[ 4, 16, 16 ] PPI::Token::Operator '=' 76[ 4, 17, 17 ] PPI::Token::Whitespace ' ' 77[ 4, 18, 18 ] PPI::Token::Number '3' 78[ 4, 19, 19 ] PPI::Token::Whitespace ' ' 79[ 4, 21, 21 ] PPI::Token::Whitespace '\n' 80 PPI::Statement::Compound 81[ 5, 1, 1 ] PPI::Token::Word 'if' 82[ 5, 3, 3 ] PPI::Token::Whitespace ' ' 83 PPI::Structure::Condition ( ... ) 84 PPI::Statement::Expression 85[ 5, 5, 5 ] PPI::Token::Number '1' 86[ 5, 7, 7 ] PPI::Token::Whitespace ' ' 87 PPI::Structure::Block { ... } 88[ 5, 9, 9 ] PPI::Token::Whitespace ' ' 89 PPI::Statement 90[ 5, 10, 10 ] PPI::Token::Symbol '$w' 91[ 5, 12, 12 ] PPI::Token::Whitespace ' ' 92[ 5, 13, 13 ] PPI::Token::Operator '=' 93[ 5, 14, 14 ] PPI::Token::Whitespace ' ' 94[ 5, 15, 15 ] PPI::Token::Number '4' 95[ 5, 16, 16 ] PPI::Token::Whitespace ' ' 96[ 5, 18, 18 ] PPI::Token::Whitespace '\n' 97 PPI::Statement::Compound 98[ 6, 1, 1 ] PPI::Token::Word 'unless' 99[ 6, 7, 7 ] PPI::Token::Whitespace ' ' 100 PPI::Structure::Condition ( ... ) 101 PPI::Statement::Expression 102[ 6, 9, 9 ] PPI::Token::Number '1' 103[ 6, 11, 11 ] PPI::Token::Whitespace ' ' 104 PPI::Structure::Block { ... } 105[ 6, 13, 13 ] PPI::Token::Whitespace ' ' 106 PPI::Statement 107[ 6, 14, 14 ] PPI::Token::Symbol '$v' 108[ 6, 16, 16 ] PPI::Token::Whitespace ' ' 109[ 6, 17, 17 ] PPI::Token::Operator '=' 110[ 6, 18, 18 ] PPI::Token::Whitespace ' ' 111[ 6, 19, 19 ] PPI::Token::Number '5' 112[ 6, 20, 20 ] PPI::Token::Whitespace ' ' 113[ 6, 22, 22 ] PPI::Token::Whitespace '\n' 114 PPI::Statement::Compound 115[ 7, 1, 1 ] PPI::Token::Word 'for' 116[ 7, 4, 4 ] PPI::Token::Whitespace ' ' 117 PPI::Structure::List ( ... ) 118 PPI::Statement 119[ 7, 6, 6 ] PPI::Token::Number '1' 120[ 7, 8, 8 ] PPI::Token::Whitespace ' ' 121 PPI::Structure::Block { ... } 122[ 7, 10, 10 ] PPI::Token::Whitespace ' ' 123 PPI::Statement 124[ 7, 11, 11 ] PPI::Token::Symbol '$u' 125[ 7, 13, 13 ] PPI::Token::Whitespace ' ' 126[ 7, 14, 14 ] PPI::Token::Operator '=' 127[ 7, 15, 15 ] PPI::Token::Whitespace ' ' 128[ 7, 16, 16 ] PPI::Token::Number '6' 129[ 7, 17, 17 ] PPI::Token::Whitespace ' ' 130[ 7, 19, 19 ] PPI::Token::Whitespace '\n' 131 PPI::Statement::Compound 132[ 8, 1, 1 ] PPI::Token::Word 'foreach' 133[ 8, 8, 8 ] PPI::Token::Whitespace ' ' 134 PPI::Structure::List ( ... ) 135 PPI::Statement 136[ 8, 10, 10 ] PPI::Token::Number '1' 137[ 8, 12, 12 ] PPI::Token::Whitespace ' ' 138 PPI::Structure::Block { ... } 139[ 8, 14, 14 ] PPI::Token::Whitespace ' ' 140 PPI::Statement 141[ 8, 15, 15 ] PPI::Token::Symbol '$t' 142[ 8, 17, 17 ] PPI::Token::Whitespace ' ' 143[ 8, 18, 18 ] PPI::Token::Operator '=' 144[ 8, 19, 19 ] PPI::Token::Whitespace ' ' 145[ 8, 20, 20 ] PPI::Token::Number '7' 146[ 8, 21, 21 ] PPI::Token::Whitespace ' ' 147[ 8, 23, 23 ] PPI::Token::Whitespace '\n' 148 PPI::Statement::Given 149[ 9, 1, 1 ] PPI::Token::Word 'given' 150[ 9, 6, 6 ] PPI::Token::Whitespace ' ' 151 PPI::Structure::Given ( ... ) 152 PPI::Statement::Expression 153[ 9, 8, 8 ] PPI::Token::Number '1' 154[ 9, 10, 10 ] PPI::Token::Whitespace ' ' 155 PPI::Structure::Block { ... } 156[ 9, 12, 12 ] PPI::Token::Whitespace ' ' 157 PPI::Statement 158[ 9, 13, 13 ] PPI::Token::Symbol '$s' 159[ 9, 15, 15 ] PPI::Token::Whitespace ' ' 160[ 9, 16, 16 ] PPI::Token::Operator '=' 161[ 9, 17, 17 ] PPI::Token::Whitespace ' ' 162[ 9, 18, 18 ] PPI::Token::Number '8' 163[ 9, 19, 19 ] PPI::Token::Whitespace ' ' 164[ 9, 21, 21 ] PPI::Token::Whitespace '\n' 165 PPI::Statement::When 166[ 10, 1, 1 ] PPI::Token::Word 'when' 167[ 10, 5, 5 ] PPI::Token::Whitespace ' ' 168 PPI::Structure::When ( ... ) 169 PPI::Statement::Expression 170[ 10, 7, 7 ] PPI::Token::Number '1' 171[ 10, 9, 9 ] PPI::Token::Whitespace ' ' 172 PPI::Structure::Block { ... } 173[ 10, 11, 11 ] PPI::Token::Whitespace ' ' 174 PPI::Statement 175[ 10, 12, 12 ] PPI::Token::Symbol '$r' 176[ 10, 14, 14 ] PPI::Token::Whitespace ' ' 177[ 10, 15, 15 ] PPI::Token::Operator '=' 178[ 10, 16, 16 ] PPI::Token::Whitespace ' ' 179[ 10, 17, 17 ] PPI::Token::Number '9' 180[ 10, 18, 18 ] PPI::Token::Whitespace ' ' 181[ 10, 20, 20 ] PPI::Token::Whitespace '\n' 182END_EXPECTED 183 ); 184 185 _test($source, \%expected, 'Single namespace.'); 186} 187 188 189{ 190 my $source = <<'END_SOURCE'; 191$x = 1; 192END_SOURCE 193 194 my %expected = ( 195 main => [ <<'END_EXPECTED' ], 196 PPI::Document 197 PPI::Statement 198[ 1, 1, 1 ] PPI::Token::Symbol '$x' 199[ 1, 3, 3 ] PPI::Token::Whitespace ' ' 200[ 1, 4, 4 ] PPI::Token::Operator '=' 201[ 1, 5, 5 ] PPI::Token::Whitespace ' ' 202[ 1, 6, 6 ] PPI::Token::Number '1' 203[ 1, 7, 7 ] PPI::Token::Structure ';' 204[ 1, 8, 8 ] PPI::Token::Whitespace '\n' 205END_EXPECTED 206 ); 207 208 _test($source, \%expected, 'Default namespace.'); 209} 210 211 212{ 213 my $source = <<'END_SOURCE'; 214$x = 1; 215 216package Foo; 217 218$y = 2; 219END_SOURCE 220 221 my %expected = ( 222 main => [ <<'END_EXPECTED_MAIN' ], 223 PPI::Document::Fragment 224 PPI::Statement 225[ 1, 1, 1 ] PPI::Token::Symbol '$x' 226[ 1, 3, 3 ] PPI::Token::Whitespace ' ' 227[ 1, 4, 4 ] PPI::Token::Operator '=' 228[ 1, 5, 5 ] PPI::Token::Whitespace ' ' 229[ 1, 6, 6 ] PPI::Token::Number '1' 230[ 1, 7, 7 ] PPI::Token::Structure ';' 231[ 1, 8, 8 ] PPI::Token::Whitespace '\n' 232[ 2, 1, 1 ] PPI::Token::Whitespace '\n' 233END_EXPECTED_MAIN 234 235 Foo => [ <<'END_EXPECTED_FOO' ], 236 PPI::Document::Fragment 237 PPI::Statement::Package 238[ 3, 1, 1 ] PPI::Token::Word 'package' 239[ 3, 8, 8 ] PPI::Token::Whitespace ' ' 240[ 3, 9, 9 ] PPI::Token::Word 'Foo' 241[ 3, 12, 12 ] PPI::Token::Structure ';' 242[ 3, 13, 13 ] PPI::Token::Whitespace '\n' 243[ 4, 1, 1 ] PPI::Token::Whitespace '\n' 244 PPI::Statement 245[ 5, 1, 1 ] PPI::Token::Symbol '$y' 246[ 5, 3, 3 ] PPI::Token::Whitespace ' ' 247[ 5, 4, 4 ] PPI::Token::Operator '=' 248[ 5, 5, 5 ] PPI::Token::Whitespace ' ' 249[ 5, 6, 6 ] PPI::Token::Number '2' 250[ 5, 7, 7 ] PPI::Token::Structure ';' 251[ 5, 8, 8 ] PPI::Token::Whitespace '\n' 252END_EXPECTED_FOO 253 ); 254 255 _test($source, \%expected, 'Simple multiple namespaces: default followed by non-default.'); 256} 257 258 259{ 260 my $source = <<'END_SOURCE'; 261package Foo; 262$x = 1; 263 264package main; 265 266$y = 2; 267END_SOURCE 268 269 my %expected = ( 270 main => [ <<'END_EXPECTED_MAIN' ], 271 PPI::Document::Fragment 272 PPI::Statement::Package 273[ 4, 1, 1 ] PPI::Token::Word 'package' 274[ 4, 8, 8 ] PPI::Token::Whitespace ' ' 275[ 4, 9, 9 ] PPI::Token::Word 'main' 276[ 4, 13, 13 ] PPI::Token::Structure ';' 277[ 4, 14, 14 ] PPI::Token::Whitespace '\n' 278[ 5, 1, 1 ] PPI::Token::Whitespace '\n' 279 PPI::Statement 280[ 6, 1, 1 ] PPI::Token::Symbol '$y' 281[ 6, 3, 3 ] PPI::Token::Whitespace ' ' 282[ 6, 4, 4 ] PPI::Token::Operator '=' 283[ 6, 5, 5 ] PPI::Token::Whitespace ' ' 284[ 6, 6, 6 ] PPI::Token::Number '2' 285[ 6, 7, 7 ] PPI::Token::Structure ';' 286[ 6, 8, 8 ] PPI::Token::Whitespace '\n' 287END_EXPECTED_MAIN 288 289 Foo => [ <<'END_EXPECTED_FOO' ], 290 PPI::Document::Fragment 291 PPI::Statement::Package 292[ 1, 1, 1 ] PPI::Token::Word 'package' 293[ 1, 8, 8 ] PPI::Token::Whitespace ' ' 294[ 1, 9, 9 ] PPI::Token::Word 'Foo' 295[ 1, 12, 12 ] PPI::Token::Structure ';' 296[ 1, 13, 13 ] PPI::Token::Whitespace '\n' 297 PPI::Statement 298[ 2, 1, 1 ] PPI::Token::Symbol '$x' 299[ 2, 3, 3 ] PPI::Token::Whitespace ' ' 300[ 2, 4, 4 ] PPI::Token::Operator '=' 301[ 2, 5, 5 ] PPI::Token::Whitespace ' ' 302[ 2, 6, 6 ] PPI::Token::Number '1' 303[ 2, 7, 7 ] PPI::Token::Structure ';' 304[ 2, 8, 8 ] PPI::Token::Whitespace '\n' 305[ 3, 1, 1 ] PPI::Token::Whitespace '\n' 306END_EXPECTED_FOO 307 ); 308 309 _test($source, \%expected, 'Simple multiple namespaces: non-default followed by default.'); 310} 311 312 313{ 314 my $source = <<'END_SOURCE'; 315$x = 1; 316package Foo; 317$y = 2; 318package main; 319$z = 3; 320package Foo; 321$w = 4; 322package main; 323$v = 5; 324END_SOURCE 325 326 my %expected = ( 327 main => [ <<'END_EXPECTED_MAIN' ], 328 PPI::Document::Fragment 329 PPI::Statement 330[ 1, 1, 1 ] PPI::Token::Symbol '$x' 331[ 1, 3, 3 ] PPI::Token::Whitespace ' ' 332[ 1, 4, 4 ] PPI::Token::Operator '=' 333[ 1, 5, 5 ] PPI::Token::Whitespace ' ' 334[ 1, 6, 6 ] PPI::Token::Number '1' 335[ 1, 7, 7 ] PPI::Token::Structure ';' 336[ 1, 8, 8 ] PPI::Token::Whitespace '\n' 337 PPI::Statement::Package 338[ 4, 1, 1 ] PPI::Token::Word 'package' 339[ 4, 8, 8 ] PPI::Token::Whitespace ' ' 340[ 4, 9, 9 ] PPI::Token::Word 'main' 341[ 4, 13, 13 ] PPI::Token::Structure ';' 342[ 4, 14, 14 ] PPI::Token::Whitespace '\n' 343 PPI::Statement 344[ 5, 1, 1 ] PPI::Token::Symbol '$z' 345[ 5, 3, 3 ] PPI::Token::Whitespace ' ' 346[ 5, 4, 4 ] PPI::Token::Operator '=' 347[ 5, 5, 5 ] PPI::Token::Whitespace ' ' 348[ 5, 6, 6 ] PPI::Token::Number '3' 349[ 5, 7, 7 ] PPI::Token::Structure ';' 350[ 5, 8, 8 ] PPI::Token::Whitespace '\n' 351 PPI::Statement::Package 352[ 8, 1, 1 ] PPI::Token::Word 'package' 353[ 8, 8, 8 ] PPI::Token::Whitespace ' ' 354[ 8, 9, 9 ] PPI::Token::Word 'main' 355[ 8, 13, 13 ] PPI::Token::Structure ';' 356[ 8, 14, 14 ] PPI::Token::Whitespace '\n' 357 PPI::Statement 358[ 9, 1, 1 ] PPI::Token::Symbol '$v' 359[ 9, 3, 3 ] PPI::Token::Whitespace ' ' 360[ 9, 4, 4 ] PPI::Token::Operator '=' 361[ 9, 5, 5 ] PPI::Token::Whitespace ' ' 362[ 9, 6, 6 ] PPI::Token::Number '5' 363[ 9, 7, 7 ] PPI::Token::Structure ';' 364[ 9, 8, 8 ] PPI::Token::Whitespace '\n' 365END_EXPECTED_MAIN 366 367 Foo => [ <<'END_EXPECTED_FOO' ], 368 PPI::Document::Fragment 369 PPI::Statement::Package 370[ 2, 1, 1 ] PPI::Token::Word 'package' 371[ 2, 8, 8 ] PPI::Token::Whitespace ' ' 372[ 2, 9, 9 ] PPI::Token::Word 'Foo' 373[ 2, 12, 12 ] PPI::Token::Structure ';' 374[ 2, 13, 13 ] PPI::Token::Whitespace '\n' 375 PPI::Statement 376[ 3, 1, 1 ] PPI::Token::Symbol '$y' 377[ 3, 3, 3 ] PPI::Token::Whitespace ' ' 378[ 3, 4, 4 ] PPI::Token::Operator '=' 379[ 3, 5, 5 ] PPI::Token::Whitespace ' ' 380[ 3, 6, 6 ] PPI::Token::Number '2' 381[ 3, 7, 7 ] PPI::Token::Structure ';' 382[ 3, 8, 8 ] PPI::Token::Whitespace '\n' 383 PPI::Statement::Package 384[ 6, 1, 1 ] PPI::Token::Word 'package' 385[ 6, 8, 8 ] PPI::Token::Whitespace ' ' 386[ 6, 9, 9 ] PPI::Token::Word 'Foo' 387[ 6, 12, 12 ] PPI::Token::Structure ';' 388[ 6, 13, 13 ] PPI::Token::Whitespace '\n' 389 PPI::Statement 390[ 7, 1, 1 ] PPI::Token::Symbol '$w' 391[ 7, 3, 3 ] PPI::Token::Whitespace ' ' 392[ 7, 4, 4 ] PPI::Token::Operator '=' 393[ 7, 5, 5 ] PPI::Token::Whitespace ' ' 394[ 7, 6, 6 ] PPI::Token::Number '4' 395[ 7, 7, 7 ] PPI::Token::Structure ';' 396[ 7, 8, 8 ] PPI::Token::Whitespace '\n' 397END_EXPECTED_FOO 398 ); 399 400 _test( 401 $source, 402 \%expected, 403 'Simple multiple namespaces: back and forth between two.', 404 ); 405} 406 407 408{ 409 my $source = <<'END_SOURCE'; 410$x = 1; 411 412{ 413 package Foo; 414 $a = 17; 415} 416 417$y = 2; 418END_SOURCE 419 420 my %expected = ( 421 main => [ <<'END_EXPECTED_MAIN' ], 422 PPI::Document::Fragment 423 PPI::Statement 424[ 1, 1, 1 ] PPI::Token::Symbol '$x' 425[ 1, 3, 3 ] PPI::Token::Whitespace ' ' 426[ 1, 4, 4 ] PPI::Token::Operator '=' 427[ 1, 5, 5 ] PPI::Token::Whitespace ' ' 428[ 1, 6, 6 ] PPI::Token::Number '1' 429[ 1, 7, 7 ] PPI::Token::Structure ';' 430[ 1, 8, 8 ] PPI::Token::Whitespace '\n' 431[ 2, 1, 1 ] PPI::Token::Whitespace '\n' 432 PPI::Statement::Compound 433 PPI::Structure::Block { ... } 434[ 3, 2, 2 ] PPI::Token::Whitespace '\n' 435[ 4, 1, 1 ] PPI::Token::Whitespace ' ' 436[ 6, 2, 2 ] PPI::Token::Whitespace '\n' 437[ 7, 1, 1 ] PPI::Token::Whitespace '\n' 438 PPI::Statement 439[ 8, 1, 1 ] PPI::Token::Symbol '$y' 440[ 8, 3, 3 ] PPI::Token::Whitespace ' ' 441[ 8, 4, 4 ] PPI::Token::Operator '=' 442[ 8, 5, 5 ] PPI::Token::Whitespace ' ' 443[ 8, 6, 6 ] PPI::Token::Number '2' 444[ 8, 7, 7 ] PPI::Token::Structure ';' 445[ 8, 8, 8 ] PPI::Token::Whitespace '\n' 446END_EXPECTED_MAIN 447 448 Foo => [ <<'END_EXPECTED_FOO' ], 449 PPI::Document::Fragment 450 PPI::Statement::Package 451[ 4, 5, 5 ] PPI::Token::Word 'package' 452[ 4, 12, 12 ] PPI::Token::Whitespace ' ' 453[ 4, 13, 13 ] PPI::Token::Word 'Foo' 454[ 4, 16, 16 ] PPI::Token::Structure ';' 455[ 4, 17, 17 ] PPI::Token::Whitespace '\n' 456[ 5, 1, 1 ] PPI::Token::Whitespace ' ' 457 PPI::Statement 458[ 5, 5, 5 ] PPI::Token::Symbol '$a' 459[ 5, 7, 7 ] PPI::Token::Whitespace ' ' 460[ 5, 8, 8 ] PPI::Token::Operator '=' 461[ 5, 9, 9 ] PPI::Token::Whitespace ' ' 462[ 5, 10, 10 ] PPI::Token::Number '17' 463[ 5, 12, 12 ] PPI::Token::Structure ';' 464[ 5, 13, 13 ] PPI::Token::Whitespace '\n' 465END_EXPECTED_FOO 466 ); 467 468 _test($source, \%expected, 'Single lexically scoped namespace: scope block.'); 469} 470 471 472{ 473 my $source = <<'END_SOURCE'; 474$x = 1; 475 476foreach qw< l m n > { 477 package Foo; 478 $a = 17; 479} 480 481$y = 2; 482END_SOURCE 483 484 my %expected = ( 485 main => [ <<'END_EXPECTED_MAIN' ], 486 PPI::Document::Fragment 487 PPI::Statement 488[ 1, 1, 1 ] PPI::Token::Symbol '$x' 489[ 1, 3, 3 ] PPI::Token::Whitespace ' ' 490[ 1, 4, 4 ] PPI::Token::Operator '=' 491[ 1, 5, 5 ] PPI::Token::Whitespace ' ' 492[ 1, 6, 6 ] PPI::Token::Number '1' 493[ 1, 7, 7 ] PPI::Token::Structure ';' 494[ 1, 8, 8 ] PPI::Token::Whitespace '\n' 495[ 2, 1, 1 ] PPI::Token::Whitespace '\n' 496 PPI::Statement::Compound 497[ 3, 1, 1 ] PPI::Token::Word 'foreach' 498[ 3, 8, 8 ] PPI::Token::Whitespace ' ' 499[ 3, 9, 9 ] PPI::Token::QuoteLike::Words 'qw< l m n >' 500[ 3, 20, 20 ] PPI::Token::Whitespace ' ' 501 PPI::Structure::Block { ... } 502[ 3, 22, 22 ] PPI::Token::Whitespace '\n' 503[ 4, 1, 1 ] PPI::Token::Whitespace ' ' 504[ 6, 2, 2 ] PPI::Token::Whitespace '\n' 505[ 7, 1, 1 ] PPI::Token::Whitespace '\n' 506 PPI::Statement 507[ 8, 1, 1 ] PPI::Token::Symbol '$y' 508[ 8, 3, 3 ] PPI::Token::Whitespace ' ' 509[ 8, 4, 4 ] PPI::Token::Operator '=' 510[ 8, 5, 5 ] PPI::Token::Whitespace ' ' 511[ 8, 6, 6 ] PPI::Token::Number '2' 512[ 8, 7, 7 ] PPI::Token::Structure ';' 513[ 8, 8, 8 ] PPI::Token::Whitespace '\n' 514END_EXPECTED_MAIN 515 516 Foo => [ <<'END_EXPECTED_FOO' ], 517 PPI::Document::Fragment 518 PPI::Statement::Package 519[ 4, 5, 5 ] PPI::Token::Word 'package' 520[ 4, 12, 12 ] PPI::Token::Whitespace ' ' 521[ 4, 13, 13 ] PPI::Token::Word 'Foo' 522[ 4, 16, 16 ] PPI::Token::Structure ';' 523[ 4, 17, 17 ] PPI::Token::Whitespace '\n' 524[ 5, 1, 1 ] PPI::Token::Whitespace ' ' 525 PPI::Statement 526[ 5, 5, 5 ] PPI::Token::Symbol '$a' 527[ 5, 7, 7 ] PPI::Token::Whitespace ' ' 528[ 5, 8, 8 ] PPI::Token::Operator '=' 529[ 5, 9, 9 ] PPI::Token::Whitespace ' ' 530[ 5, 10, 10 ] PPI::Token::Number '17' 531[ 5, 12, 12 ] PPI::Token::Structure ';' 532[ 5, 13, 13 ] PPI::Token::Whitespace '\n' 533END_EXPECTED_FOO 534 ); 535 536 _test( 537 $source, 538 \%expected, 539 'Single lexically scoped namespace: foreach loop.', 540 ); 541} 542 543 544{ 545 my $source = <<'END_SOURCE'; 546$x = 1; 547 548given qw< l m n > { 549 package Foo; 550 $a = 17; 551} 552 553$y = 2; 554END_SOURCE 555 556 my %expected = ( 557 main => [ <<'END_EXPECTED_MAIN' ], 558 PPI::Document::Fragment 559 PPI::Statement 560[ 1, 1, 1 ] PPI::Token::Symbol '$x' 561[ 1, 3, 3 ] PPI::Token::Whitespace ' ' 562[ 1, 4, 4 ] PPI::Token::Operator '=' 563[ 1, 5, 5 ] PPI::Token::Whitespace ' ' 564[ 1, 6, 6 ] PPI::Token::Number '1' 565[ 1, 7, 7 ] PPI::Token::Structure ';' 566[ 1, 8, 8 ] PPI::Token::Whitespace '\n' 567[ 2, 1, 1 ] PPI::Token::Whitespace '\n' 568 PPI::Statement::Given 569[ 3, 1, 1 ] PPI::Token::Word 'given' 570[ 3, 6, 6 ] PPI::Token::Whitespace ' ' 571[ 3, 7, 7 ] PPI::Token::QuoteLike::Words 'qw< l m n >' 572[ 3, 18, 18 ] PPI::Token::Whitespace ' ' 573 PPI::Structure::Block { ... } 574[ 3, 20, 20 ] PPI::Token::Whitespace '\n' 575[ 4, 1, 1 ] PPI::Token::Whitespace ' ' 576[ 6, 2, 2 ] PPI::Token::Whitespace '\n' 577[ 7, 1, 1 ] PPI::Token::Whitespace '\n' 578 PPI::Statement 579[ 8, 1, 1 ] PPI::Token::Symbol '$y' 580[ 8, 3, 3 ] PPI::Token::Whitespace ' ' 581[ 8, 4, 4 ] PPI::Token::Operator '=' 582[ 8, 5, 5 ] PPI::Token::Whitespace ' ' 583[ 8, 6, 6 ] PPI::Token::Number '2' 584[ 8, 7, 7 ] PPI::Token::Structure ';' 585[ 8, 8, 8 ] PPI::Token::Whitespace '\n' 586END_EXPECTED_MAIN 587 588 Foo => [ <<'END_EXPECTED_FOO' ], 589 PPI::Document::Fragment 590 PPI::Statement::Package 591[ 4, 5, 5 ] PPI::Token::Word 'package' 592[ 4, 12, 12 ] PPI::Token::Whitespace ' ' 593[ 4, 13, 13 ] PPI::Token::Word 'Foo' 594[ 4, 16, 16 ] PPI::Token::Structure ';' 595[ 4, 17, 17 ] PPI::Token::Whitespace '\n' 596[ 5, 1, 1 ] PPI::Token::Whitespace ' ' 597 PPI::Statement 598[ 5, 5, 5 ] PPI::Token::Symbol '$a' 599[ 5, 7, 7 ] PPI::Token::Whitespace ' ' 600[ 5, 8, 8 ] PPI::Token::Operator '=' 601[ 5, 9, 9 ] PPI::Token::Whitespace ' ' 602[ 5, 10, 10 ] PPI::Token::Number '17' 603[ 5, 12, 12 ] PPI::Token::Structure ';' 604[ 5, 13, 13 ] PPI::Token::Whitespace '\n' 605END_EXPECTED_FOO 606 ); 607 608 _test( 609 $source, 610 \%expected, 611 'Single lexically scoped namespace: given.', 612 ); 613} 614 615 616{ 617 my $source = <<'END_SOURCE'; 618$x = 1; 619 620when qw< l m n > { 621 package Foo; 622 $a = 17; 623} 624 625$y = 2; 626END_SOURCE 627 628 my %expected = ( 629 main => [ <<'END_EXPECTED_MAIN' ], 630 PPI::Document::Fragment 631 PPI::Statement 632[ 1, 1, 1 ] PPI::Token::Symbol '$x' 633[ 1, 3, 3 ] PPI::Token::Whitespace ' ' 634[ 1, 4, 4 ] PPI::Token::Operator '=' 635[ 1, 5, 5 ] PPI::Token::Whitespace ' ' 636[ 1, 6, 6 ] PPI::Token::Number '1' 637[ 1, 7, 7 ] PPI::Token::Structure ';' 638[ 1, 8, 8 ] PPI::Token::Whitespace '\n' 639[ 2, 1, 1 ] PPI::Token::Whitespace '\n' 640 PPI::Statement::When 641[ 3, 1, 1 ] PPI::Token::Word 'when' 642[ 3, 5, 5 ] PPI::Token::Whitespace ' ' 643[ 3, 6, 6 ] PPI::Token::QuoteLike::Words 'qw< l m n >' 644[ 3, 17, 17 ] PPI::Token::Whitespace ' ' 645 PPI::Structure::Block { ... } 646[ 3, 19, 19 ] PPI::Token::Whitespace '\n' 647[ 4, 1, 1 ] PPI::Token::Whitespace ' ' 648[ 6, 2, 2 ] PPI::Token::Whitespace '\n' 649[ 7, 1, 1 ] PPI::Token::Whitespace '\n' 650 PPI::Statement 651[ 8, 1, 1 ] PPI::Token::Symbol '$y' 652[ 8, 3, 3 ] PPI::Token::Whitespace ' ' 653[ 8, 4, 4 ] PPI::Token::Operator '=' 654[ 8, 5, 5 ] PPI::Token::Whitespace ' ' 655[ 8, 6, 6 ] PPI::Token::Number '2' 656[ 8, 7, 7 ] PPI::Token::Structure ';' 657[ 8, 8, 8 ] PPI::Token::Whitespace '\n' 658END_EXPECTED_MAIN 659 660 Foo => [ <<'END_EXPECTED_FOO' ], 661 PPI::Document::Fragment 662 PPI::Statement::Package 663[ 4, 5, 5 ] PPI::Token::Word 'package' 664[ 4, 12, 12 ] PPI::Token::Whitespace ' ' 665[ 4, 13, 13 ] PPI::Token::Word 'Foo' 666[ 4, 16, 16 ] PPI::Token::Structure ';' 667[ 4, 17, 17 ] PPI::Token::Whitespace '\n' 668[ 5, 1, 1 ] PPI::Token::Whitespace ' ' 669 PPI::Statement 670[ 5, 5, 5 ] PPI::Token::Symbol '$a' 671[ 5, 7, 7 ] PPI::Token::Whitespace ' ' 672[ 5, 8, 8 ] PPI::Token::Operator '=' 673[ 5, 9, 9 ] PPI::Token::Whitespace ' ' 674[ 5, 10, 10 ] PPI::Token::Number '17' 675[ 5, 12, 12 ] PPI::Token::Structure ';' 676[ 5, 13, 13 ] PPI::Token::Whitespace '\n' 677END_EXPECTED_FOO 678 ); 679 680 _test( 681 $source, 682 \%expected, 683 'Single lexically scoped namespace: when.', 684 ); 685} 686 687 688{ 689 my $source = <<'END_SOURCE'; 690given (0) { 691 package Foo; 692 when (1) { 693 package main; 694 } 695 when (2) { 696 package main; 697 } 698 default { 699 package main; 700 while (3) { 701 package Foo; 702 package Bar; 703 package Foo; 704 package main; 705 foreach (4) { 706 package Foo; 707 } 708 } 709 } 710} 711END_SOURCE 712 713 my %expected = ( 714 main => [ 715<<'END_EXPECTED_MAIN', 716 PPI::Document::Fragment 717 PPI::Statement::Given 718[ 1, 1, 1 ] PPI::Token::Word 'given' 719[ 1, 6, 6 ] PPI::Token::Whitespace ' ' 720 PPI::Structure::Given ( ... ) 721 PPI::Statement::Expression 722[ 1, 8, 8 ] PPI::Token::Number '0' 723[ 1, 10, 10 ] PPI::Token::Whitespace ' ' 724 PPI::Structure::Block { ... } 725[ 1, 12, 12 ] PPI::Token::Whitespace '\n' 726[ 2, 1, 1 ] PPI::Token::Whitespace ' ' 727[ 21, 2, 2 ] PPI::Token::Whitespace '\n' 728END_EXPECTED_MAIN 729<<'END_EXPECTED_MAIN', 730 PPI::Document::Fragment 731 PPI::Statement::Package 732[ 4, 9, 9 ] PPI::Token::Word 'package' 733[ 4, 16, 16 ] PPI::Token::Whitespace ' ' 734[ 4, 17, 17 ] PPI::Token::Word 'main' 735[ 4, 21, 21 ] PPI::Token::Structure ';' 736[ 4, 22, 22 ] PPI::Token::Whitespace '\n' 737[ 5, 1, 1 ] PPI::Token::Whitespace ' ' 738END_EXPECTED_MAIN 739<<'END_EXPECTED_MAIN', 740 PPI::Document::Fragment 741 PPI::Statement::Package 742[ 7, 9, 9 ] PPI::Token::Word 'package' 743[ 7, 16, 16 ] PPI::Token::Whitespace ' ' 744[ 7, 17, 17 ] PPI::Token::Word 'main' 745[ 7, 21, 21 ] PPI::Token::Structure ';' 746[ 7, 22, 22 ] PPI::Token::Whitespace '\n' 747[ 8, 1, 1 ] PPI::Token::Whitespace ' ' 748END_EXPECTED_MAIN 749<<'END_EXPECTED_MAIN', 750 PPI::Document::Fragment 751 PPI::Statement::Package 752[ 10, 9, 9 ] PPI::Token::Word 'package' 753[ 10, 16, 16 ] PPI::Token::Whitespace ' ' 754[ 10, 17, 17 ] PPI::Token::Word 'main' 755[ 10, 21, 21 ] PPI::Token::Structure ';' 756[ 10, 22, 22 ] PPI::Token::Whitespace '\n' 757[ 11, 1, 1 ] PPI::Token::Whitespace ' ' 758 PPI::Statement::Compound 759[ 11, 9, 9 ] PPI::Token::Word 'while' 760[ 11, 14, 14 ] PPI::Token::Whitespace ' ' 761 PPI::Structure::Condition ( ... ) 762 PPI::Statement::Expression 763[ 11, 16, 16 ] PPI::Token::Number '3' 764[ 11, 18, 18 ] PPI::Token::Whitespace ' ' 765 PPI::Structure::Block { ... } 766[ 11, 20, 20 ] PPI::Token::Whitespace '\n' 767[ 12, 1, 1 ] PPI::Token::Whitespace ' ' 768 PPI::Statement::Package 769[ 15, 13, 13 ] PPI::Token::Word 'package' 770[ 15, 20, 20 ] PPI::Token::Whitespace ' ' 771[ 15, 21, 21 ] PPI::Token::Word 'main' 772[ 15, 25, 25 ] PPI::Token::Structure ';' 773[ 15, 26, 26 ] PPI::Token::Whitespace '\n' 774[ 16, 1, 1 ] PPI::Token::Whitespace ' ' 775 PPI::Statement::Compound 776[ 16, 13, 13 ] PPI::Token::Word 'foreach' 777[ 16, 20, 20 ] PPI::Token::Whitespace ' ' 778 PPI::Structure::List ( ... ) 779 PPI::Statement 780[ 16, 22, 22 ] PPI::Token::Number '4' 781[ 16, 24, 24 ] PPI::Token::Whitespace ' ' 782 PPI::Structure::Block { ... } 783[ 16, 26, 26 ] PPI::Token::Whitespace '\n' 784[ 17, 1, 1 ] PPI::Token::Whitespace ' ' 785[ 18, 14, 14 ] PPI::Token::Whitespace '\n' 786[ 19, 1, 1 ] PPI::Token::Whitespace ' ' 787[ 19, 10, 10 ] PPI::Token::Whitespace '\n' 788[ 20, 1, 1 ] PPI::Token::Whitespace ' ' 789END_EXPECTED_MAIN 790 ], 791 792 Foo => [ 793<<'END_EXPECTED_FOO', 794 PPI::Document::Fragment 795 PPI::Statement::Package 796[ 2, 5, 5 ] PPI::Token::Word 'package' 797[ 2, 12, 12 ] PPI::Token::Whitespace ' ' 798[ 2, 13, 13 ] PPI::Token::Word 'Foo' 799[ 2, 16, 16 ] PPI::Token::Structure ';' 800[ 2, 17, 17 ] PPI::Token::Whitespace '\n' 801[ 3, 1, 1 ] PPI::Token::Whitespace ' ' 802 PPI::Statement::When 803[ 3, 5, 5 ] PPI::Token::Word 'when' 804[ 3, 9, 9 ] PPI::Token::Whitespace ' ' 805 PPI::Structure::When ( ... ) 806 PPI::Statement::Expression 807[ 3, 11, 11 ] PPI::Token::Number '1' 808[ 3, 13, 13 ] PPI::Token::Whitespace ' ' 809 PPI::Structure::Block { ... } 810[ 3, 15, 15 ] PPI::Token::Whitespace '\n' 811[ 4, 1, 1 ] PPI::Token::Whitespace ' ' 812[ 5, 6, 6 ] PPI::Token::Whitespace '\n' 813[ 6, 1, 1 ] PPI::Token::Whitespace ' ' 814 PPI::Statement::When 815[ 6, 5, 5 ] PPI::Token::Word 'when' 816[ 6, 9, 9 ] PPI::Token::Whitespace ' ' 817 PPI::Structure::When ( ... ) 818 PPI::Statement::Expression 819[ 6, 11, 11 ] PPI::Token::Number '2' 820[ 6, 13, 13 ] PPI::Token::Whitespace ' ' 821 PPI::Structure::Block { ... } 822[ 6, 15, 15 ] PPI::Token::Whitespace '\n' 823[ 7, 1, 1 ] PPI::Token::Whitespace ' ' 824[ 8, 6, 6 ] PPI::Token::Whitespace '\n' 825[ 9, 1, 1 ] PPI::Token::Whitespace ' ' 826 PPI::Statement::When 827[ 9, 5, 5 ] PPI::Token::Word 'default' 828[ 9, 12, 12 ] PPI::Token::Whitespace ' ' 829 PPI::Structure::Block { ... } 830[ 9, 14, 14 ] PPI::Token::Whitespace '\n' 831[ 10, 1, 1 ] PPI::Token::Whitespace ' ' 832[ 20, 6, 6 ] PPI::Token::Whitespace '\n' 833END_EXPECTED_FOO 834<<'END_EXPECTED_FOO', 835 PPI::Document::Fragment 836 PPI::Statement::Package 837[ 12, 13, 13 ] PPI::Token::Word 'package' 838[ 12, 20, 20 ] PPI::Token::Whitespace ' ' 839[ 12, 21, 21 ] PPI::Token::Word 'Foo' 840[ 12, 24, 24 ] PPI::Token::Structure ';' 841[ 12, 25, 25 ] PPI::Token::Whitespace '\n' 842[ 13, 1, 1 ] PPI::Token::Whitespace ' ' 843 PPI::Statement::Package 844[ 14, 13, 13 ] PPI::Token::Word 'package' 845[ 14, 20, 20 ] PPI::Token::Whitespace ' ' 846[ 14, 21, 21 ] PPI::Token::Word 'Foo' 847[ 14, 24, 24 ] PPI::Token::Structure ';' 848[ 14, 25, 25 ] PPI::Token::Whitespace '\n' 849[ 15, 1, 1 ] PPI::Token::Whitespace ' ' 850END_EXPECTED_FOO 851<<'END_EXPECTED_FOO', 852 PPI::Document::Fragment 853 PPI::Statement::Package 854[ 17, 17, 17 ] PPI::Token::Word 'package' 855[ 17, 24, 24 ] PPI::Token::Whitespace ' ' 856[ 17, 25, 25 ] PPI::Token::Word 'Foo' 857[ 17, 28, 28 ] PPI::Token::Structure ';' 858[ 17, 29, 29 ] PPI::Token::Whitespace '\n' 859[ 18, 1, 1 ] PPI::Token::Whitespace ' ' 860END_EXPECTED_FOO 861 ], 862 863 Bar => [ <<'END_EXPECTED_BAR' ], 864 PPI::Document::Fragment 865 PPI::Statement::Package 866[ 13, 13, 13 ] PPI::Token::Word 'package' 867[ 13, 20, 20 ] PPI::Token::Whitespace ' ' 868[ 13, 21, 21 ] PPI::Token::Word 'Bar' 869[ 13, 24, 24 ] PPI::Token::Structure ';' 870[ 13, 25, 25 ] PPI::Token::Whitespace '\n' 871[ 14, 1, 1 ] PPI::Token::Whitespace ' ' 872END_EXPECTED_BAR 873 ); 874 875 _test( 876 $source, 877 \%expected, 878 'Heavilly nested namespaces.', 879 ); 880} 881 882 883sub _test { 884 my ($source, $expected_ref, $test_name) = @_; 885 886 my $document = PPI::Document->new(\$source); 887 888 my %expanded_expected; 889 foreach my $namespace ( keys %{$expected_ref} ) { 890 my $strings = $expected_ref->{$namespace}; 891 $expanded_expected{$namespace} = 892 [ map { [ split m/ \n /x ] } @{$strings} ]; 893 } 894 895 my $got = split_ppi_node_by_namespace($document); 896 my %got_expanded; 897 foreach my $namespace ( keys %{$got} ) { 898 my $ppi_doms = $got->{$namespace}; 899 $got_expanded{$namespace} = 900 [ 901 map { 902 [ map { _expand_tabs($_) } _new_dumper($_)->list() ] 903 } 904 @{$ppi_doms} 905 ]; 906 } 907 908 is_deeply(\%got_expanded, \%expanded_expected, $test_name) 909 or diag( 910 Data::Dumper->Dump( 911 [\%got_expanded, \%expanded_expected], 912 [ qw<got_expanded expanded_expected> ], 913 ) 914 ); 915 916 return; 917} 918 919 920sub _new_dumper { 921 my ($node) = @_; 922 923 return PPI::Dumper->new($node, indent => $DUMP_INDENT, locations => 1); 924} 925 926 927# Why Adam had to put @#$^@#$&^ hard tabs in his dumper output, I don't know. 928sub _expand_tabs { 929 my ($string) = @_; 930 931 while ( 932 $string =~ 933 s< \A ( [^\t]* ) ( \t+ ) > 934 <$1 . ( ' ' x (length($2) * $DUMP_INDENT - length($1) % $DUMP_INDENT) )>xe 935 ) { 936 # Nothing here. 937 } 938 939 return $string; 940} 941 942done_testing; 943