@@ -348,17 +348,29 @@ public function append(array $data, $id = null, bool $append = true, $linesToBeC
348
348
349
349
$ this ->tests [$ id ] = ['size ' => $ size , 'status ' => $ status ];
350
350
351
- foreach ($ data as $ file => $ lines ) {
351
+ foreach ($ data as $ file => $ fileData ) {
352
352
if (!$ this ->filter ->isFile ($ file )) {
353
353
continue ;
354
354
}
355
355
356
- foreach ($ lines as $ k => $ v ) {
357
- if ($ v === Driver::LINE_EXECUTED ) {
358
- if (empty ($ this ->data [$ file ][$ k ]) || !\in_array ($ id , $ this ->data [$ file ][$ k ])) {
359
- $ this ->data [$ file ][$ k ][] = $ id ;
356
+ foreach ($ fileData ['lines ' ] as $ line => $ lineCoverage ) {
357
+ if ($ lineCoverage === Driver::LINE_EXECUTED ) {
358
+ $ this ->addCoverageLinePathCovered ($ file , $ line , true );
359
+ $ this ->addCoverageLineTest ($ file , $ line , $ id );
360
+ }
361
+ }
362
+
363
+ foreach ($ fileData ['functions ' ] as $ function => $ functionCoverage ) {
364
+ foreach ($ functionCoverage ['branches ' ] as $ branch => $ branchCoverage ) {
365
+ if (($ branchCoverage ['hit ' ] ?? 0 ) === 1 ) {
366
+ $ this ->addCoverageBranchHit ($ file , $ function , $ branch , $ branchCoverage ['hit ' ] ?? 0 );
367
+ $ this ->addCoverageBranchTest ($ file , $ function , $ branch , $ id );
360
368
}
361
369
}
370
+
371
+ foreach ($ functionCoverage ['paths ' ] as $ path => $ pathCoverage ) {
372
+ $ this ->addCoveragePathHit ($ file , $ function , $ path , $ pathCoverage ['hit ' ] ?? 0 );
373
+ }
362
374
}
363
375
}
364
376
@@ -376,10 +388,13 @@ public function merge(self $that): void
376
388
\array_merge ($ this ->filter ->getWhitelistedFiles (), $ that ->filter ()->getWhitelistedFiles ())
377
389
);
378
390
379
- foreach ($ that ->data as $ file => $ lines ) {
380
- if (!isset ($ this ->data [$ file ])) {
391
+ $ thisData = $ this ->getData ();
392
+ $ thatData = $ that ->getData ();
393
+
394
+ foreach ($ thatData as $ file => $ fileData ) {
395
+ if (!isset ($ thisData [$ file ])) {
381
396
if (!$ this ->filter ->isFiltered ($ file )) {
382
- $ this -> data [$ file ] = $ lines ;
397
+ $ thisData [$ file ] = $ fileData ;
383
398
}
384
399
385
400
continue ;
@@ -388,27 +403,30 @@ public function merge(self $that): void
388
403
// we should compare the lines if any of two contains data
389
404
$ compareLineNumbers = \array_unique (
390
405
\array_merge (
391
- \array_keys ($ this -> data [$ file ]),
392
- \array_keys ($ that -> data [$ file ])
406
+ \array_keys ($ thisData [$ file][ ' lines ' ]),
407
+ \array_keys ($ thatData [$ file ][ ' lines ' ]) // can this be $fileData?
393
408
)
394
409
);
395
410
396
411
foreach ($ compareLineNumbers as $ line ) {
397
- $ thatPriority = $ this ->getLinePriority ($ that -> data [$ file ], $ line );
398
- $ thisPriority = $ this ->getLinePriority ($ this -> data [$ file ], $ line );
412
+ $ thatPriority = $ this ->getLinePriority ($ thatData [$ file][ ' lines ' ], $ line );
413
+ $ thisPriority = $ this ->getLinePriority ($ thisData [$ file][ ' lines ' ], $ line );
399
414
400
415
if ($ thatPriority > $ thisPriority ) {
401
- $ this ->data [$ file ][$ line ] = $ that ->data [$ file ][$ line ];
402
- } elseif ($ thatPriority === $ thisPriority && \is_array ($ this ->data [$ file ][$ line ])) {
403
- $ this ->data [$ file ][$ line ] = \array_unique (
404
- \array_merge ($ this ->data [$ file ][$ line ], $ that ->data [$ file ][$ line ])
416
+ $ thisData [$ file ]['lines ' ][$ line ] = $ thatData [$ file ]['lines ' ][$ line ];
417
+ } elseif ($ thatPriority === $ thisPriority && \is_array ($ thisData [$ file ]['lines ' ][$ line ])) {
418
+ if ($ line ['pathCovered ' ] === true ) {
419
+ $ thisData [$ file ]['lines ' ][$ line ]['pathCovered ' ] = $ line ['pathCovered ' ];
420
+ }
421
+ $ thisData [$ file ]['lines ' ][$ line ] = \array_unique (
422
+ \array_merge ($ thisData [$ file ]['lines ' ][$ line ], $ thatData [$ file ]['lines ' ][$ line ])
405
423
);
406
424
}
407
425
}
408
426
}
409
427
410
- $ this ->tests = \array_merge ($ this ->tests , $ that ->getTests ());
411
- $ this ->report = null ;
428
+ $ this ->tests = \array_merge ($ this ->tests , $ that ->getTests ());
429
+ $ this ->setData ( $ thisData ) ;
412
430
}
413
431
414
432
public function setCacheTokens (bool $ flag ): void
@@ -493,12 +511,9 @@ public function setDetermineBranchCoverage(bool $flag): void
493
511
*
494
512
* During a merge, a higher number is better.
495
513
*
496
- * @param array $data
497
- * @param int $line
498
- *
499
514
* @return int
500
515
*/
501
- private function getLinePriority ($ data , $ line )
516
+ private function getLinePriority (array $ data , int $ line )
502
517
{
503
518
if (!\array_key_exists ($ line , $ data )) {
504
519
return 1 ;
@@ -533,7 +548,10 @@ private function applyCoversAnnotationFilter(array &$data, $linesToBeCovered, ar
533
548
throw new MissingCoversAnnotationException ;
534
549
}
535
550
536
- $ data = [];
551
+ $ data = [
552
+ 'lines ' => [],
553
+ 'functions ' => [],
554
+ ];
537
555
538
556
return ;
539
557
}
@@ -544,7 +562,7 @@ private function applyCoversAnnotationFilter(array &$data, $linesToBeCovered, ar
544
562
545
563
if ($ this ->checkForUnintentionallyCoveredCode &&
546
564
(!$ this ->currentId instanceof TestCase ||
547
- (!$ this ->currentId ->isMedium () && !$ this ->currentId ->isLarge ()))) {
565
+ (!$ this ->currentId ->isMedium () && !$ this ->currentId ->isLarge ()))) {
548
566
$ this ->performUnintentionallyCoveredCodeCheck ($ data , $ linesToBeCovered , $ linesToBeUsed );
549
567
}
550
568
@@ -556,7 +574,11 @@ private function applyCoversAnnotationFilter(array &$data, $linesToBeCovered, ar
556
574
557
575
foreach (\array_keys ($ data ) as $ filename ) {
558
576
$ _linesToBeCovered = \array_flip ($ linesToBeCovered [$ filename ]);
559
- $ data [$ filename ] = \array_intersect_key ($ data [$ filename ], $ _linesToBeCovered );
577
+
578
+ $ data [$ filename ]['lines ' ] = \array_intersect_key (
579
+ $ data [$ filename ],
580
+ $ _linesToBeCovered
581
+ );
560
582
}
561
583
}
562
584
@@ -580,22 +602,208 @@ private function applyIgnoredLinesFilter(array &$data): void
580
602
}
581
603
582
604
foreach ($ this ->getLinesToBeIgnored ($ filename ) as $ line ) {
583
- unset($ data [$ filename ][$ line ]);
605
+ unset($ data [$ filename ][' lines ' ][ $ line ]);
584
606
}
585
607
}
586
608
}
587
609
588
610
private function initializeFilesThatAreSeenTheFirstTime (array $ data ): void
589
611
{
590
- foreach ($ data as $ file => $ lines ) {
591
- if (!isset ($ this ->data [$ file ]) && $ this ->filter ->isFile ($ file )) {
592
- $ this ->data [$ file ] = [];
612
+ foreach ($ data as $ file => $ fileData ) {
613
+ if (isset ($ this ->data [$ file ]) || !$ this ->filter ->isFile ($ file )) {
614
+ continue ;
615
+ }
616
+ $ this ->initializeFileCoverageData ($ file );
593
617
594
- foreach ($ lines as $ k => $ v ) {
595
- $ this ->data [$ file ][$ k ] = $ v === -2 ? null : [];
618
+ // If this particular line is identified as not covered, mark it as null
619
+ foreach ($ fileData ['lines ' ] as $ lineNumber => $ flag ) {
620
+ if ($ flag === Driver::LINE_NOT_EXECUTABLE ) {
621
+ $ this ->data [$ file ]['lines ' ][$ lineNumber ] = null ;
596
622
}
597
623
}
624
+
625
+ foreach ($ fileData ['functions ' ] as $ functionName => $ functionData ) {
626
+ // @todo - should this have a helper to merge covered paths?
627
+ $ this ->data [$ file ]['paths ' ][$ functionName ] = $ functionData ['paths ' ];
628
+
629
+ foreach ($ functionData ['branches ' ] as $ branchIndex => $ branchData ) {
630
+ $ this ->addCoverageBranchHit ($ file , $ functionName , $ branchIndex , $ branchData ['hit ' ]);
631
+ $ this ->addCoverageBranchLineStart ($ file , $ functionName , $ branchIndex , $ branchData ['line_start ' ]);
632
+ $ this ->addCoverageBranchLineEnd ($ file , $ functionName , $ branchIndex , $ branchData ['line_end ' ]);
633
+
634
+ for ($ curLine = $ branchData ['line_start ' ]; $ curLine < $ branchData ['line_end ' ]; $ curLine ++) {
635
+ if (isset ($ this ->data [$ file ]['lines ' ][$ curLine ])) {
636
+ $ this ->addCoverageLinePathCovered ($ file , $ curLine , (bool ) $ branchData ['hit ' ]);
637
+ }
638
+ }
639
+ }
640
+ }
641
+ }
642
+ }
643
+
644
+ private function initializeFileCoverageData (string $ file ): void
645
+ {
646
+ if (!isset ($ this ->data [$ file ]) && $ this ->filter ->isFile ($ file )) {
647
+ $ this ->data [$ file ] = [
648
+ 'lines ' => [],
649
+ 'branches ' => [],
650
+ 'paths ' => [],
651
+ ];
652
+ }
653
+ }
654
+
655
+ private function addCoverageLinePathCovered (string $ file , int $ lineNumber , bool $ isCovered ): void
656
+ {
657
+ $ this ->initializeFileCoverageData ($ file );
658
+
659
+ // Initialize the data coverage array for this line
660
+ if (!isset ($ this ->data [$ file ]['lines ' ][$ lineNumber ])) {
661
+ $ this ->data [$ file ]['lines ' ][$ lineNumber ] = [
662
+ 'pathCovered ' => false ,
663
+ 'tests ' => [],
664
+ ];
665
+ }
666
+
667
+ $ this ->data [$ file ]['lines ' ][$ lineNumber ]['pathCovered ' ] = $ isCovered ;
668
+ }
669
+
670
+ private function addCoverageLineTest (string $ file , int $ lineNumber , string $ testId ): void
671
+ {
672
+ $ this ->initializeFileCoverageData ($ file );
673
+
674
+ // Initialize the data coverage array for this line
675
+ if (!isset ($ this ->data [$ file ]['lines ' ][$ lineNumber ])) {
676
+ $ this ->data [$ file ]['lines ' ][$ lineNumber ] = [
677
+ 'pathCovered ' => false ,
678
+ 'tests ' => [],
679
+ ];
680
+ }
681
+
682
+ if (!\in_array ($ testId , $ this ->data [$ file ]['lines ' ][$ lineNumber ]['tests ' ], true )) {
683
+ $ this ->data [$ file ]['lines ' ][$ lineNumber ]['tests ' ][] = $ testId ;
684
+ }
685
+ }
686
+
687
+ private function addCoverageBranchHit (string $ file , string $ functionName , int $ branchIndex , int $ hit ): void
688
+ {
689
+ $ this ->initializeFileCoverageData ($ file );
690
+
691
+ if (!\array_key_exists ($ functionName , $ this ->data [$ file ]['branches ' ])) {
692
+ $ this ->data [$ file ]['branches ' ][$ functionName ] = [];
693
+ }
694
+
695
+ if (!\array_key_exists ($ branchIndex , $ this ->data [$ file ]['branches ' ][$ functionName ])) {
696
+ $ this ->data [$ file ]['branches ' ][$ functionName ][$ branchIndex ] = [
697
+ 'hit ' => 0 ,
698
+ 'line_start ' => 0 ,
699
+ 'line_end ' => 0 ,
700
+ 'tests ' => [],
701
+ ];
598
702
}
703
+
704
+ $ this ->data [$ file ]['branches ' ][$ functionName ][$ branchIndex ]['hit ' ] = \max (
705
+ $ this ->data [$ file ]['branches ' ][$ functionName ][$ branchIndex ]['hit ' ],
706
+ $ hit
707
+ );
708
+ }
709
+
710
+ private function addCoverageBranchLineStart (
711
+ string $ file ,
712
+ string $ functionName ,
713
+ int $ branchIndex ,
714
+ int $ lineStart
715
+ ): void {
716
+ $ this ->initializeFileCoverageData ($ file );
717
+
718
+ if (!\array_key_exists ($ functionName , $ this ->data [$ file ]['branches ' ])) {
719
+ $ this ->data [$ file ]['branches ' ][$ functionName ] = [];
720
+ }
721
+
722
+ if (!\array_key_exists ($ branchIndex , $ this ->data [$ file ]['branches ' ][$ functionName ])) {
723
+ $ this ->data [$ file ]['branches ' ][$ functionName ][$ branchIndex ] = [
724
+ 'hit ' => 0 ,
725
+ 'line_start ' => 0 ,
726
+ 'line_end ' => 0 ,
727
+ 'tests ' => [],
728
+ ];
729
+ }
730
+
731
+ $ this ->data [$ file ]['branches ' ][$ functionName ][$ branchIndex ]['line_start ' ] = $ lineStart ;
732
+ }
733
+
734
+ private function addCoverageBranchLineEnd (
735
+ string $ file ,
736
+ string $ functionName ,
737
+ int $ branchIndex ,
738
+ int $ lineEnd
739
+ ): void {
740
+ $ this ->initializeFileCoverageData ($ file );
741
+
742
+ if (!\array_key_exists ($ functionName , $ this ->data [$ file ]['branches ' ])) {
743
+ $ this ->data [$ file ]['branches ' ][$ functionName ] = [];
744
+ }
745
+
746
+ if (!\array_key_exists ($ branchIndex , $ this ->data [$ file ]['branches ' ][$ functionName ])) {
747
+ $ this ->data [$ file ]['branches ' ][$ functionName ][$ branchIndex ] = [
748
+ 'hit ' => 0 ,
749
+ 'line_start ' => 0 ,
750
+ 'line_end ' => 0 ,
751
+ 'tests ' => [],
752
+ ];
753
+ }
754
+
755
+ $ this ->data [$ file ]['branches ' ][$ functionName ][$ branchIndex ]['line_end ' ] = $ lineEnd ;
756
+ }
757
+
758
+ private function addCoverageBranchTest (
759
+ string $ file ,
760
+ string $ functionName ,
761
+ int $ branchIndex ,
762
+ string $ testId
763
+ ): void {
764
+ $ this ->initializeFileCoverageData ($ file );
765
+
766
+ if (!\array_key_exists ($ functionName , $ this ->data [$ file ]['branches ' ])) {
767
+ $ this ->data [$ file ]['branches ' ][$ functionName ] = [];
768
+ }
769
+
770
+ if (!\array_key_exists ($ branchIndex , $ this ->data [$ file ]['branches ' ][$ functionName ])) {
771
+ $ this ->data [$ file ]['branches ' ][$ functionName ][$ branchIndex ] = [
772
+ 'hit ' => 0 ,
773
+ 'line_start ' => 0 ,
774
+ 'line_end ' => 0 ,
775
+ 'tests ' => [],
776
+ ];
777
+ }
778
+
779
+ if (!\in_array ($ testId , $ this ->data [$ file ]['branches ' ][$ functionName ][$ branchIndex ]['tests ' ], true )) {
780
+ $ this ->data [$ file ]['branches ' ][$ functionName ][$ branchIndex ]['tests ' ][] = $ testId ;
781
+ }
782
+ }
783
+
784
+ private function addCoveragePathHit (
785
+ string $ file ,
786
+ string $ functionName ,
787
+ int $ pathId ,
788
+ int $ hit
789
+ ): void {
790
+ $ this ->initializeFileCoverageData ($ file );
791
+
792
+ if (!\array_key_exists ($ functionName , $ this ->data [$ file ]['paths ' ])) {
793
+ $ this ->data [$ file ]['paths ' ][$ functionName ] = [];
794
+ }
795
+
796
+ if (!\array_key_exists ($ pathId , $ this ->data [$ file ]['paths ' ][$ functionName ])) {
797
+ $ this ->data [$ file ]['paths ' ][$ functionName ][$ pathId ] = [
798
+ 'hit ' => 0 ,
799
+ 'path ' => [],
800
+ ];
801
+ }
802
+
803
+ $ this ->data [$ file ]['paths ' ][$ functionName ][$ pathId ]['hit ' ] = \max (
804
+ $ this ->data [$ file ]['paths ' ][$ functionName ][$ pathId ]['hit ' ],
805
+ $ hit
806
+ );
599
807
}
600
808
601
809
/**
@@ -619,13 +827,17 @@ private function addUncoveredFilesFromWhitelist(): void
619
827
continue ;
620
828
}
621
829
622
- $ data [$ uncoveredFile ] = [];
830
+ $ data [$ uncoveredFile ] = [
831
+ 'lines ' => [],
832
+ 'functions ' => [],
833
+ ];
623
834
624
835
$ lines = \count (\file ($ uncoveredFile ));
625
836
626
- for ($ i = 1 ; $ i <= $ lines ; $ i ++) {
627
- $ data [$ uncoveredFile ][$ i ] = Driver::LINE_NOT_EXECUTED ;
837
+ for ($ line = 1 ; $ line <= $ lines ; $ line ++) {
838
+ $ data [$ uncoveredFile ][' lines ' ][ $ line ] = Driver::LINE_NOT_EXECUTED ;
628
839
}
840
+ // @todo - do the same here with functions and paths
629
841
}
630
842
631
843
$ this ->append ($ data , 'UNCOVERED_FILES_FROM_WHITELIST ' );
@@ -817,10 +1029,10 @@ private function performUnintentionallyCoveredCodeCheck(array &$data, array $lin
817
1029
818
1030
$ unintentionallyCoveredUnits = [];
819
1031
820
- foreach ($ data as $ file => $ _data ) {
821
- foreach ($ _data as $ line => $ flag ) {
822
- if ($ flag === 1 && !isset ($ allowedLines [$ file ][$ line ])) {
823
- $ unintentionallyCoveredUnits [] = $ this ->wizard ->lookup ($ file , $ line );
1032
+ foreach ($ data as $ file => $ fileData ) {
1033
+ foreach ($ fileData [ ' lines ' ] as $ lineNumber => $ flag ) {
1034
+ if ($ flag === 1 && !isset ($ allowedLines [$ file ][$ lineNumber ])) {
1035
+ $ unintentionallyCoveredUnits [] = $ this ->wizard ->lookup ($ file , $ lineNumber );
824
1036
}
825
1037
}
826
1038
}
0 commit comments