@@ -3,9 +3,12 @@ package test
33import dotty .partest .DPConfig
44import dotty .tools .dotc .{Main , Bench , Driver }
55import dotty .tools .dotc .reporting .Reporter
6+ import dotty .tools .dotc .util .SourcePosition
7+ import dotty .tools .dotc .config .CompilerCommand
68import scala .collection .mutable .ListBuffer
7- import scala .reflect .io .{ Path , Directory , File => SFile }
9+ import scala .reflect .io .{ Path , Directory , File => SFile , AbstractFile }
810import scala .tools .partest .nest .{ FileManager , NestUI }
11+ import scala .annotation .tailrec
912import java .io .{ RandomAccessFile , File => JFile }
1013
1114import org .junit .Test
@@ -178,13 +181,83 @@ abstract class CompilerTest {
178181
179182 // ========== HELPERS =============
180183
181- private def compileArgs (args : Array [String ], xerrors : Int = 0 )(implicit defaultOptions : List [String ]): Unit = {
184+ private def compileArgs (args : Array [String ], xerrors : Int = 0 )
185+ (implicit defaultOptions : List [String ]): Unit = {
182186 val allArgs = args ++ defaultOptions
183187 val processor = if (allArgs.exists(_.startsWith(" #" ))) Bench else Main
184- val nerrors = processor.process(allArgs).errorCount
188+ val reporter = processor.process(allArgs)
189+
190+ val nerrors = reporter.errorCount
185191 assert(nerrors == xerrors, s " Wrong # of errors. Expected: $xerrors, found: $nerrors" )
192+
193+ // is neg test, check errors occur on right line
194+ if (xerrors > 0 ) {
195+ val errorLines = reporter.allErrors.map(_.pos)
196+ // reporter didn't record as many errors as its errorCount says
197+ assert(errorLines.length == nerrors, s " Not enough errors recorded. " )
198+ val (byFile, noPos) = errorLines.groupBy(_.source.file).partition(_._1.toString != " <no source>" )
199+
200+ // check the compiler errors that have a source position
201+ val noPosErrFiles = byFile.foldLeft(0 )(_ + checkErrorsInFile(_))
202+
203+ // check that files without compiler errors don't contain error markers
204+ val allFiles = (allArgs filter {
205+ case arg => arg.endsWith(" .scala" ) || arg.endsWith(" .java" )
206+ }).toList
207+ val checkedFiles = byFile.keys.toList.map(_.toString)
208+ val noPosExpected = noPosErrFiles + checkNoErrorMissing(allFiles.filter(! checkedFiles.contains(_)))
209+
210+ // check compiler errors without source position, their number should
211+ // correspond to all "// nopos-error" markers in any files
212+ val noPosFound = noPos.foldLeft(0 )(_ + _._2.length)
213+ assert(noPosFound == noPosExpected,
214+ s " Wrong # of errors without source position. Expected (all files): $noPosExpected, found (compiler): $noPosFound" )
215+ }
186216 }
187217
218+ /** For neg tests, check that all errors thrown by compiler have a "// error"
219+ * on the corresponding line in the source file.
220+ */
221+ def checkErrorsInFile (errors : (AbstractFile , List [SourcePosition ])): Int = {
222+ errors match {
223+ case (fileName, pos@ (first :: rest)) =>
224+ val content = first.source.content.mkString
225+ val (line, rest) = content.span(_ != '\n ' )
226+ val byLine = scala.collection.mutable.Map (errors._2.groupBy(_.line).toSeq: _* )
227+
228+ @ tailrec
229+ def checkLine (line : String , rest : String , index : Int ): Unit = {
230+ val expected = countErrors(line)
231+ byLine.remove(index) match {
232+ case Some (pos) => checkErrors(fileName.toString, Some (index), expected, pos.length)
233+ case None => checkErrors(fileName.toString, Some (index), expected, 0 )
234+ }
235+ val (newLine, newRest) = rest.span(_ != '\n ' )
236+ if (! newRest.isEmpty)
237+ checkLine(newLine, newRest.drop(1 ), index + 1 )
238+ }
239+
240+ checkLine(line, rest.drop(1 ), 0 )
241+ assert(byLine.isEmpty, " Some compiler errors don't correspond to any line in the source file: " + fileName + " : " + byLine)
242+ countNoPosErrors(content)
243+ case (fileName, Nil ) => assert(false , " impossible: empty groupBy value in file: " + fileName); 0
244+ }
245+ }
246+
247+ def countErrors (s : String ) = " // ?error" .r.findAllIn(s).length
248+ def countNoPosErrors (s : String ) = " // ?nopos-error" .r.findAllIn(s).length
249+
250+ def checkErrors (fileName : String , index : Option [Int ], exp : Int , found : Int ) = {
251+ val i = index.map({ i => " :" + (i + 1 ) }).getOrElse(" " )
252+ assert(found == exp, s " Wrong # of errors for $fileName$i. Expected (file): $exp, found (compiler): $found" )
253+ }
254+
255+ def checkNoErrorMissing (files : List [String ]) = files.foldLeft(0 )({ case (sum, fileName) =>
256+ val content = SFile (fileName).slurp
257+ checkErrors(fileName, None , countErrors(content), 0 )
258+ sum + countNoPosErrors(content)
259+ })
260+
188261 // In particular, don't copy flags from scalac tests
189262 private val extensionsToCopy = scala.collection.immutable.HashSet (" scala" , " java" )
190263
0 commit comments