2929use function array_merge ;
3030use function is_int ;
3131use function is_string ;
32+ use function Safe \preg_match ;
3233use function sprintf ;
34+ use function substr ;
35+ use function substr_count ;
36+ use const PREG_OFFSET_CAPTURE ;
3337
3438/**
3539 * @internal
@@ -60,6 +64,7 @@ public static function parseSpecFile(
6064 $ relativePath = basename ($ sourceDir ).'/ ' .$ file ->getRelativePathname ();
6165
6266 yield $ relativePath .': ' .$ title => self ::parseSpec (
67+ $ file ->getContents (),
6368 $ relativePath ,
6469 $ meta ,
6570 $ title ,
@@ -91,6 +96,7 @@ private static function checkSpecFileSchema(mixed $specs): void
9196 }
9297
9398 private static function parseSpec (
99+ string $ fileContents ,
94100 string $ file ,
95101 Meta $ meta ,
96102 int |string $ title ,
@@ -102,6 +108,11 @@ private static function parseSpec(
102108 is_int ($ title ) ? 'spec # ' .$ title : $ title ,
103109 );
104110
111+ $ lineNumber = self ::findLineNumber ($ fileContents , $ title );
112+ if (null !== $ lineNumber ) {
113+ $ file .= ': ' .$ lineNumber ;
114+ }
115+
105116 $ specWithConfig = is_string ($ specWithConfigOrSimpleSpec )
106117 ? SpecWithConfig::fromSimpleSpec ($ specWithConfigOrSimpleSpec )
107118 : $ specWithConfigOrSimpleSpec ;
@@ -120,6 +131,29 @@ private static function parseSpec(
120131 );
121132 }
122133
134+ /**
135+ * @return positive-int|0
136+ */
137+ private static function findLineNumber (string $ fileContents , int |string $ title ): ?int
138+ {
139+ if (is_int ($ title )) {
140+ return null ;
141+ }
142+
143+ $ titleRegex = sprintf (
144+ '/ * \'%s \' => (?:SpecWithConfig|<<< \'PHP \')/ ' ,
145+ $ title ,
146+ );
147+
148+ if (1 !== preg_match ($ titleRegex , $ fileContents , $ matches , PREG_OFFSET_CAPTURE )) {
149+ return null ;
150+ }
151+
152+ $ titlePosition = $ matches [0 ][1 ];
153+
154+ return substr_count (substr ($ fileContents , 0 , $ titlePosition ), "\n" ) + 1 ;
155+ }
156+
123157 private static function createSymbolsConfiguration (
124158 SpecWithConfig $ specWithConfig ,
125159 Meta $ meta ,
0 commit comments