Added presentation compiler tests. review by phaller, extempore.
git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@24075 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
parent
e2ccd40f32
commit
9c215faff7
|
@ -1567,11 +1567,14 @@ BOOTRAPING TEST AND TEST SUITE
|
||||||
<shootouttests dir="${partest.dir}/${partest.srcdir}/shootout" includes="*.scala"/>
|
<shootouttests dir="${partest.dir}/${partest.srcdir}/shootout" includes="*.scala"/>
|
||||||
<scalaptests dir="${partest.dir}/${partest.srcdir}/scalap" includes="**/*.scala"/>
|
<scalaptests dir="${partest.dir}/${partest.srcdir}/scalap" includes="**/*.scala"/>
|
||||||
<scalachecktests dir="${partest.dir}/${partest.srcdir}/scalacheck">
|
<scalachecktests dir="${partest.dir}/${partest.srcdir}/scalacheck">
|
||||||
<include name="*.scala"/>
|
<include name="*.scala"/>
|
||||||
</scalachecktests>
|
</scalachecktests>
|
||||||
<specializedtests dir="${partest.dir}/${partest.srcdir}/specialized">
|
<specializedtests dir="${partest.dir}/${partest.srcdir}/specialized">
|
||||||
<include name="*.scala"/>
|
<include name="*.scala"/>
|
||||||
</specializedtests>
|
</specializedtests>
|
||||||
|
<presentationtests dir="${partest.dir}/${partest.srcdir}/presentation">
|
||||||
|
<include name="*/*.scala"/>
|
||||||
|
</presentationtests>
|
||||||
<!-- <scripttests dir="${partest.dir}/${partest.srcdir}/script" includes="*.scala"/> -->
|
<!-- <scripttests dir="${partest.dir}/${partest.srcdir}/script" includes="*.scala"/> -->
|
||||||
</partest>
|
</partest>
|
||||||
</target>
|
</target>
|
||||||
|
|
|
@ -0,0 +1,175 @@
|
||||||
|
package scala.tools.nsc.interactive
|
||||||
|
package tests
|
||||||
|
|
||||||
|
import scala.tools.nsc.Settings
|
||||||
|
import scala.tools.nsc.reporters.StoreReporter
|
||||||
|
import scala.tools.nsc.util.{BatchSourceFile, SourceFile, Position}
|
||||||
|
import scala.tools.nsc.io._
|
||||||
|
|
||||||
|
import scala.collection.{immutable, mutable}
|
||||||
|
|
||||||
|
/** A base class for writing interactive compiler tests.
|
||||||
|
*
|
||||||
|
* This class tries to cover common functionality needed when testing the presentation
|
||||||
|
* compiler: instantiation source files, reloading, creating positions, instantiating
|
||||||
|
* the presentation compiler, random stress testing.
|
||||||
|
*
|
||||||
|
* By default, this class loads all classes found under `src/`. They are found in
|
||||||
|
* `sourceFiles`. Positions can be created using `pos(file, line, col)`. The presentation
|
||||||
|
* compiler is available through `compiler`.
|
||||||
|
*
|
||||||
|
* It is easy to test member completion and type at a given position. Source
|
||||||
|
* files are searched for /markers/. By default, the completion marker is `/*!*/` and the
|
||||||
|
* typedAt marker is `/*?*/`. Place these markers in your source files, and call `completionTests`
|
||||||
|
* and `typedAtTests` to print the results at all these positions. Sources are reloaded by `reloadSources`
|
||||||
|
* (blocking call). All ask operations are placed on the work queue without waiting for each one to
|
||||||
|
* complete before asking the next. After all asks, it waits for each response in turn and prints the result.
|
||||||
|
* The default timout is 5 seconds per operation.
|
||||||
|
*
|
||||||
|
* The same mechanism can be used for custom operations. Use `askAllSources(marker)(f)(g)`. Give your custom
|
||||||
|
* marker, and provide the two functions: one for creating the request, and the second for processing the
|
||||||
|
* response, if it didn't time out and there was no error.
|
||||||
|
*
|
||||||
|
* @see Check existing tests under test/files/presentation
|
||||||
|
*
|
||||||
|
* @author Iulian Dragos
|
||||||
|
*/
|
||||||
|
abstract class InteractiveTest {
|
||||||
|
|
||||||
|
val completionMarker = "/*!*/"
|
||||||
|
val typedAtMarker = "/*?*/"
|
||||||
|
val TIMEOUT = 5000 // 5 seconds
|
||||||
|
|
||||||
|
val settings = new Settings
|
||||||
|
val reporter= new StoreReporter
|
||||||
|
|
||||||
|
// need this so that the classpath comes from what partest
|
||||||
|
// instead of scala.home
|
||||||
|
settings.usejavacp.value = true
|
||||||
|
|
||||||
|
/** The root directory for this test suite, usually the test kind ("test/files/presentation"). */
|
||||||
|
val outDir = Path(Option(System.getProperty("partest.cwd")).getOrElse("."))
|
||||||
|
|
||||||
|
/** The base directory for this test, usually a subdirectory of "test/files/presentation/" */
|
||||||
|
val baseDir = Option(System.getProperty("partest.testname")).map(outDir / _).getOrElse(Path("."))
|
||||||
|
|
||||||
|
// settings.YpresentationDebug.value = true
|
||||||
|
lazy val compiler = new Global(settings, reporter)
|
||||||
|
|
||||||
|
def sources(filename: String*): Seq[SourceFile] =
|
||||||
|
for (f <- filename) yield
|
||||||
|
source(if (f.startsWith("/")) Path(f) else baseDir / f)
|
||||||
|
|
||||||
|
def source(file: Path) = new BatchSourceFile(AbstractFile.getFile(file.toFile))
|
||||||
|
def source(filename: String): SourceFile = new BatchSourceFile(AbstractFile.getFile(filename))
|
||||||
|
|
||||||
|
def pos(file: SourceFile, line: Int, col: Int): Position =
|
||||||
|
file.position(line, col)
|
||||||
|
|
||||||
|
def filesInDir(dir: Path): Iterator[Path] = {
|
||||||
|
dir.toDirectory.list.filter(_.isFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Where source files are placed. */
|
||||||
|
val sourceDir = "src"
|
||||||
|
|
||||||
|
/** All .scala files below "src" directory. */
|
||||||
|
lazy val sourceFiles: Array[SourceFile] =
|
||||||
|
filesInDir(baseDir / sourceDir).filter(_.extension == "scala").map(source).toArray
|
||||||
|
|
||||||
|
/** All positions of the given string in all source files. */
|
||||||
|
def allPositionsOf(sources: Seq[SourceFile] = sourceFiles, str: String): immutable.Map[SourceFile, Seq[Position]] = {
|
||||||
|
(for (s <- sources; p <- positionsOf(s, str)) yield p).groupBy(_.source)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return all positions of the given str in the given source file. */
|
||||||
|
def positionsOf(source: SourceFile, str: String): Seq[Position] = {
|
||||||
|
val buf = new mutable.ListBuffer[Position]
|
||||||
|
var pos = source.content.indexOfSlice(str)
|
||||||
|
while (pos >= 0) {
|
||||||
|
// buf += compiler.rangePos(source, pos - 1, pos - 1, pos - 1)
|
||||||
|
buf += source.position(pos - 1) // we need the position before the first character of this marker
|
||||||
|
pos = source.content.indexOfSlice(str, pos + 1)
|
||||||
|
}
|
||||||
|
buf.toList
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Perform an operation on all sources at all positions that match the given
|
||||||
|
* marker string. For instance, askAllSources("/*!*/")(askTypeAt)(println) would
|
||||||
|
* ask the tyep at all positions marked with /*!*/ and println the result.
|
||||||
|
*/
|
||||||
|
def askAllSources[T](marker: String)(askAt: Position => Response[T])(f: (Position, T) => Unit) {
|
||||||
|
val positions = allPositionsOf(str = marker).valuesIterator.toList.flatten
|
||||||
|
val responses = for (pos <- positions) yield askAt(pos)
|
||||||
|
|
||||||
|
for ((pos, r) <- positions zip responses) r.get(TIMEOUT) match {
|
||||||
|
case Some(Left(members)) =>
|
||||||
|
f(pos, members)
|
||||||
|
case None =>
|
||||||
|
println("TIMEOUT: " + r)
|
||||||
|
case _ =>
|
||||||
|
println("ERROR: " + r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Ask completion for all marked positions in all sources.
|
||||||
|
* A completion position is marked with /*!*/.
|
||||||
|
*/
|
||||||
|
def completionTests() {
|
||||||
|
askAllSources(completionMarker) { pos =>
|
||||||
|
println("askTypeCompletion at " + pos)
|
||||||
|
val r = new Response[List[compiler.Member]]
|
||||||
|
compiler.askTypeCompletion(pos, r)
|
||||||
|
r
|
||||||
|
} { (pos, members) =>
|
||||||
|
println("\n" + "=" * 80)
|
||||||
|
println("[response] aksTypeCompletion at " + (pos.line, pos.column))
|
||||||
|
println(members.sortBy(_.sym.name.toString).mkString("\n"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Ask for typedAt for all marker positions in all sources.
|
||||||
|
*/
|
||||||
|
def typeAtTests() {
|
||||||
|
askAllSources(typedAtMarker) { pos =>
|
||||||
|
println("askTypeAt at " + pos)
|
||||||
|
val r = new Response[compiler.Tree]
|
||||||
|
compiler.askTypeAt(pos, r)
|
||||||
|
r
|
||||||
|
} { (pos, tree) =>
|
||||||
|
println("[response] askTypeAt at " + (pos.line, pos.column))
|
||||||
|
println(tree)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Reload the given source files and wait for them to be reloaded. */
|
||||||
|
def reloadSources(sources: Seq[SourceFile] = sourceFiles) {
|
||||||
|
// println("basedir: " + baseDir.path)
|
||||||
|
// println("sourcedir: " + (baseDir / sourceDir).path)
|
||||||
|
println("reload: " + sourceFiles.mkString("", ", ", ""))
|
||||||
|
val reload = new Response[Unit]
|
||||||
|
compiler.askReload(sourceFiles.toList, reload)
|
||||||
|
reload.get
|
||||||
|
}
|
||||||
|
|
||||||
|
def runTest: Unit = {
|
||||||
|
if (runRandomTests) randomTests(20, sourceFiles)
|
||||||
|
completionTests()
|
||||||
|
typeAtTests()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Perform n random tests with random changes. */
|
||||||
|
def randomTests(n: Int, files: Array[SourceFile]) {
|
||||||
|
val tester = new Tester(n, files, settings)
|
||||||
|
tester.run()
|
||||||
|
}
|
||||||
|
|
||||||
|
val runRandomTests = true
|
||||||
|
|
||||||
|
def main(args: Array[String]) {
|
||||||
|
reloadSources()
|
||||||
|
runTest
|
||||||
|
compiler.askShutdown()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -153,7 +153,7 @@ class Tester(ntests: Int, inputs: Array[SourceFile], settings: Settings) {
|
||||||
changes foreach (_.deleteAll())
|
changes foreach (_.deleteAll())
|
||||||
otherTest()
|
otherTest()
|
||||||
def errorCount() = compiler.ask(() => reporter.ERROR.count)
|
def errorCount() = compiler.ask(() => reporter.ERROR.count)
|
||||||
println("\nhalf test round: "+errorCount())
|
// println("\nhalf test round: "+errorCount())
|
||||||
changes.view.reverse foreach (_.insertAll())
|
changes.view.reverse foreach (_.insertAll())
|
||||||
otherTest()
|
otherTest()
|
||||||
println("done test round: "+errorCount())
|
println("done test round: "+errorCount())
|
||||||
|
|
|
@ -71,6 +71,11 @@ class PartestTask extends Task with CompilationPathProperty {
|
||||||
def addConfiguredSpecializedTests(input: FileSet) {
|
def addConfiguredSpecializedTests(input: FileSet) {
|
||||||
specializedFiles = Some(input)
|
specializedFiles = Some(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def addConfiguredPresentationTests(input: FileSet) {
|
||||||
|
presentationFiles = Some(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def setSrcDir(input: String) {
|
def setSrcDir(input: String) {
|
||||||
srcDir = Some(input)
|
srcDir = Some(input)
|
||||||
|
@ -146,6 +151,7 @@ class PartestTask extends Task with CompilationPathProperty {
|
||||||
private var shootoutFiles: Option[FileSet] = None
|
private var shootoutFiles: Option[FileSet] = None
|
||||||
private var scalapFiles: Option[FileSet] = None
|
private var scalapFiles: Option[FileSet] = None
|
||||||
private var specializedFiles: Option[FileSet] = None
|
private var specializedFiles: Option[FileSet] = None
|
||||||
|
private var presentationFiles: Option[FileSet] = None
|
||||||
private var errorOnFailed: Boolean = false
|
private var errorOnFailed: Boolean = false
|
||||||
private var scalacOpts: Option[String] = None
|
private var scalacOpts: Option[String] = None
|
||||||
private var timeout: Option[String] = None
|
private var timeout: Option[String] = None
|
||||||
|
@ -170,14 +176,25 @@ class PartestTask extends Task with CompilationPathProperty {
|
||||||
// println("----> " + fileSet)
|
// println("----> " + fileSet)
|
||||||
|
|
||||||
val fileTests = getFiles(Some(fs)) filterNot (x => shouldExclude(x.getName))
|
val fileTests = getFiles(Some(fs)) filterNot (x => shouldExclude(x.getName))
|
||||||
val dirTests: Iterator[SPath] = fileSetToDir(fs).dirs filterNot (x => shouldExclude(x.name))
|
val dirResult = getDirs(Some(fs)) filterNot (x => shouldExclude(x.getName))
|
||||||
val dirResult = dirTests.toList.toArray map (_.jfile)
|
|
||||||
// println("dirs: " + dirResult.toList)
|
// println("dirs: " + dirResult.toList)
|
||||||
// println("files: " + fileTests.toList)
|
// println("files: " + fileTests.toList)
|
||||||
|
|
||||||
dirResult ++ fileTests
|
dirResult ++ fileTests
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private def getDirs(fileSet: Option[FileSet]): Array[File] = fileSet match {
|
||||||
|
case None => Array()
|
||||||
|
case Some(fs) =>
|
||||||
|
def shouldExclude(name: String) = (name endsWith ".obj") || (name startsWith ".")
|
||||||
|
|
||||||
|
val dirTests: Iterator[SPath] = fileSetToDir(fs).dirs filterNot (x => shouldExclude(x.name))
|
||||||
|
val dirResult = dirTests.toList.toArray map (_.jfile)
|
||||||
|
|
||||||
|
dirResult
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private def getPosFiles = getFilesAndDirs(posFiles)
|
private def getPosFiles = getFilesAndDirs(posFiles)
|
||||||
private def getNegFiles = getFilesAndDirs(negFiles)
|
private def getNegFiles = getFilesAndDirs(negFiles)
|
||||||
private def getRunFiles = getFilesAndDirs(runFiles)
|
private def getRunFiles = getFilesAndDirs(runFiles)
|
||||||
|
@ -189,6 +206,7 @@ class PartestTask extends Task with CompilationPathProperty {
|
||||||
private def getShootoutFiles = getFiles(shootoutFiles)
|
private def getShootoutFiles = getFiles(shootoutFiles)
|
||||||
private def getScalapFiles = getFiles(scalapFiles)
|
private def getScalapFiles = getFiles(scalapFiles)
|
||||||
private def getSpecializedFiles = getFiles(specializedFiles)
|
private def getSpecializedFiles = getFiles(specializedFiles)
|
||||||
|
private def getPresentationFiles = getDirs(presentationFiles)
|
||||||
|
|
||||||
override def execute() {
|
override def execute() {
|
||||||
if (isPartestDebug || debug) {
|
if (isPartestDebug || debug) {
|
||||||
|
@ -236,7 +254,8 @@ class PartestTask extends Task with CompilationPathProperty {
|
||||||
(getScriptFiles, "script", "Running script files"),
|
(getScriptFiles, "script", "Running script files"),
|
||||||
(getShootoutFiles, "shootout", "Running shootout tests"),
|
(getShootoutFiles, "shootout", "Running shootout tests"),
|
||||||
(getScalapFiles, "scalap", "Running scalap tests"),
|
(getScalapFiles, "scalap", "Running scalap tests"),
|
||||||
(getSpecializedFiles, "specialized", "Running specialized files")
|
(getSpecializedFiles, "specialized", "Running specialized files"),
|
||||||
|
(getPresentationFiles, "presentation", "Running presentation compiler test files")
|
||||||
)
|
)
|
||||||
|
|
||||||
def runSet(set: TFSet): (Int, Int, Iterable[String]) = {
|
def runSet(set: TFSet): (Int, Int, Iterable[String]) = {
|
||||||
|
|
|
@ -84,14 +84,15 @@ class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler {
|
||||||
val testRep: ExtConsoleReporter = global.reporter.asInstanceOf[ExtConsoleReporter]
|
val testRep: ExtConsoleReporter = global.reporter.asInstanceOf[ExtConsoleReporter]
|
||||||
|
|
||||||
val testFileFn: (File, FileManager) => TestFile = kind match {
|
val testFileFn: (File, FileManager) => TestFile = kind match {
|
||||||
case "pos" => PosTestFile.apply
|
case "pos" => PosTestFile.apply
|
||||||
case "neg" => NegTestFile.apply
|
case "neg" => NegTestFile.apply
|
||||||
case "run" => RunTestFile.apply
|
case "run" => RunTestFile.apply
|
||||||
case "jvm" => JvmTestFile.apply
|
case "jvm" => JvmTestFile.apply
|
||||||
case "shootout" => ShootoutTestFile.apply
|
case "shootout" => ShootoutTestFile.apply
|
||||||
case "scalap" => ScalapTestFile.apply
|
case "scalap" => ScalapTestFile.apply
|
||||||
case "scalacheck" => ScalaCheckTestFile.apply
|
case "scalacheck" => ScalaCheckTestFile.apply
|
||||||
case "specialized" => SpecializedTestFile.apply
|
case "specialized" => SpecializedTestFile.apply
|
||||||
|
case "presentation" => PresentationTestFile.apply
|
||||||
}
|
}
|
||||||
val test: TestFile = testFileFn(files.head, fileManager)
|
val test: TestFile = testFileFn(files.head, fileManager)
|
||||||
test.defineSettings(command.settings, out.isEmpty)
|
test.defineSettings(command.settings, out.isEmpty)
|
||||||
|
|
|
@ -36,7 +36,8 @@ class ConsoleRunner extends DirectRunner {
|
||||||
TestSet("script", pathFilter, "Testing script tests"),
|
TestSet("script", pathFilter, "Testing script tests"),
|
||||||
TestSet("scalacheck", x => pathFilter(x) || x.isDirectory, "Testing ScalaCheck tests"),
|
TestSet("scalacheck", x => pathFilter(x) || x.isDirectory, "Testing ScalaCheck tests"),
|
||||||
TestSet("scalap", _.isDirectory, "Run scalap decompiler tests"),
|
TestSet("scalap", _.isDirectory, "Run scalap decompiler tests"),
|
||||||
TestSet("specialized", pathFilter, "Testing specialized tests")
|
TestSet("specialized", pathFilter, "Testing specialized tests"),
|
||||||
|
TestSet("presentation", _.isDirectory, "Testing presentation compiler tests.")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +58,7 @@ class ConsoleRunner extends DirectRunner {
|
||||||
|
|
||||||
private val unaryArgs = List(
|
private val unaryArgs = List(
|
||||||
"--pack", "--all", "--verbose", "--show-diff", "--show-log",
|
"--pack", "--all", "--verbose", "--show-diff", "--show-log",
|
||||||
"--failed", "--update-check", "--version", "--ansi", "--debug"
|
"--failed", "--update-check", "--version", "--ansi", "--debug", "--help"
|
||||||
) ::: testSetArgs
|
) ::: testSetArgs
|
||||||
|
|
||||||
private val binaryArgs = List(
|
private val binaryArgs = List(
|
||||||
|
@ -71,6 +72,7 @@ class ConsoleRunner extends DirectRunner {
|
||||||
/** Early return on no args, version, or invalid args */
|
/** Early return on no args, version, or invalid args */
|
||||||
if (argstr == "") return NestUI.usage()
|
if (argstr == "") return NestUI.usage()
|
||||||
if (parsed isSet "--version") return printVersion
|
if (parsed isSet "--version") return printVersion
|
||||||
|
if (parsed isSet "--help") return NestUI.usage()
|
||||||
if (args exists (x => !denotesTestPath(x))) {
|
if (args exists (x => !denotesTestPath(x))) {
|
||||||
val invalid = (args filterNot denotesTestPath).head
|
val invalid = (args filterNot denotesTestPath).head
|
||||||
NestUI.failure("Invalid argument '%s'\n" format invalid)
|
NestUI.failure("Invalid argument '%s'\n" format invalid)
|
||||||
|
|
|
@ -55,3 +55,4 @@ case class SpecializedTestFile(file: JFile, fileManager: FileManager) extends Te
|
||||||
settings.classpath.value = ClassPath.join(PathSettings.srcSpecLib.toString, settings.classpath.value)
|
settings.classpath.value = ClassPath.join(PathSettings.srcSpecLib.toString, settings.classpath.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case class PresentationTestFile(file: JFile, fileManager: FileManager) extends TestFile("presentation")
|
||||||
|
|
|
@ -315,6 +315,7 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor
|
||||||
"-Dpartest.output="+outDir.getAbsolutePath,
|
"-Dpartest.output="+outDir.getAbsolutePath,
|
||||||
"-Dpartest.lib="+LATEST_LIB,
|
"-Dpartest.lib="+LATEST_LIB,
|
||||||
"-Dpartest.cwd="+outDir.getParent,
|
"-Dpartest.cwd="+outDir.getParent,
|
||||||
|
"-Dpartest.testname="+fileBase,
|
||||||
"-Djavacmd="+JAVACMD,
|
"-Djavacmd="+JAVACMD,
|
||||||
"-Djavaccmd="+javacCmd,
|
"-Djavaccmd="+javacCmd,
|
||||||
"-Duser.language=en -Duser.country=US"
|
"-Duser.language=en -Duser.country=US"
|
||||||
|
@ -540,7 +541,7 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor
|
||||||
execTest(outDir, logFile, PathSettings.srcSpecLib.toString)
|
execTest(outDir, logFile, PathSettings.srcSpecLib.toString)
|
||||||
diffCheck(compareOutput(dir, logFile))
|
diffCheck(compareOutput(dir, logFile))
|
||||||
})
|
})
|
||||||
|
|
||||||
def processSingleFile(file: File): LogContext = kind match {
|
def processSingleFile(file: File): LogContext = kind match {
|
||||||
case "scalacheck" =>
|
case "scalacheck" =>
|
||||||
val succFn: (File, File) => Boolean = { (logFile, outDir) =>
|
val succFn: (File, File) => Boolean = { (logFile, outDir) =>
|
||||||
|
@ -592,6 +593,9 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor
|
||||||
|
|
||||||
case "specialized" =>
|
case "specialized" =>
|
||||||
runSpecializedTest(file)
|
runSpecializedTest(file)
|
||||||
|
|
||||||
|
case "presentation" =>
|
||||||
|
runJvmTest(file) // for the moment, it's exactly the same as for a run test
|
||||||
|
|
||||||
case "buildmanager" =>
|
case "buildmanager" =>
|
||||||
val logFile = createLogFile(file)
|
val logFile = createLogFile(file)
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
reload: InteractiveTest.scala
|
||||||
|
asking position at 19:4
|
||||||
|
retrieved tree: InteractiveTest.this.settings
|
||||||
|
|
||||||
|
====================
|
||||||
|
asking position at 20:16
|
||||||
|
retrieved tree: lazy private[this] var compiler: scala.tools.nsc.interactive.CompilerControl = new Global(InteractiveTest.this.settings, InteractiveTest.this.reporter)
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
import scala.tools.nsc.interactive.tests.InteractiveTest
|
||||||
|
import scala.tools.nsc.util.Position
|
||||||
|
|
||||||
|
|
||||||
|
/** Example interactive test that does everything by hand. It would be much simpler
|
||||||
|
* to just add the markers in the test file. This test shows how to drive
|
||||||
|
* the presentation compiler manually.
|
||||||
|
*/
|
||||||
|
object Test extends InteractiveTest {
|
||||||
|
|
||||||
|
def askForPos(pos: Position) {
|
||||||
|
import compiler._
|
||||||
|
val response = new Response[Tree]
|
||||||
|
|
||||||
|
println("asking position at %d:%d".format(pos.line, pos.column))
|
||||||
|
compiler.askTypeAt(pos, response)
|
||||||
|
response.get match {
|
||||||
|
case Left(EmptyTree) =>
|
||||||
|
println("error retrieving tree at %d:%d".format(pos.line, pos.column))
|
||||||
|
case Left(t) =>
|
||||||
|
println("retrieved tree: " + t)
|
||||||
|
}
|
||||||
|
println(this.reporter.infos.mkString("\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
override def runTest {
|
||||||
|
import compiler._
|
||||||
|
val src = sourceFiles(0) // only one under src/
|
||||||
|
val pos = rangePos(src, 426, 426, 433)
|
||||||
|
val pos1 = src.position(19, 15)
|
||||||
|
|
||||||
|
// reload is issued already by the framework, but we can redo it here as an example
|
||||||
|
val reload = new Response[Unit]
|
||||||
|
compiler.askReload(List(src), reload)
|
||||||
|
reload.get // it's important to let reload finish before asking other things.
|
||||||
|
|
||||||
|
askForPos(pos)
|
||||||
|
println("=" * 20)
|
||||||
|
askForPos(pos1)
|
||||||
|
|
||||||
|
compiler.askShutdown()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package scala.tools.nsc.interactive
|
||||||
|
package tests
|
||||||
|
|
||||||
|
import scala.tools.nsc.Settings
|
||||||
|
import scala.tools.nsc.reporters.StoreReporter
|
||||||
|
import scala.tools.nsc.util.{BatchSourceFile, SourceFile, Position}
|
||||||
|
import scala.tools.nsc.io._
|
||||||
|
|
||||||
|
/** A base class for writing interactive compiler tests.
|
||||||
|
*
|
||||||
|
* @author Iulian Dragos
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
abstract class InteractiveTest {
|
||||||
|
|
||||||
|
val settings = new Settings
|
||||||
|
val reporter= new StoreReporter
|
||||||
|
|
||||||
|
settings.YpresentationDebug.value = true
|
||||||
|
lazy val compiler: CompilerControl = new Global(settings, reporter)
|
||||||
|
|
||||||
|
def sources(filename: String*): Seq[SourceFile] =
|
||||||
|
filename map source
|
||||||
|
|
||||||
|
def source(filename: String) = new BatchSourceFile(AbstractFile.getFile(filename))
|
||||||
|
|
||||||
|
def pos(filename: String, line: Int, col: Int): Position =
|
||||||
|
source(filename).position(line, col)
|
||||||
|
|
||||||
|
def runTest: Unit
|
||||||
|
|
||||||
|
def main(args: Array[String]) {
|
||||||
|
runTest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,191 @@
|
||||||
|
reload: Tester.scala
|
||||||
|
askTypeCompletion at source-/Users/dragos/workspace/git/scala/test/files/presentation/simple-tests/src/Tester.scala,line-12,offset=268
|
||||||
|
askTypeCompletion at source-/Users/dragos/workspace/git/scala/test/files/presentation/simple-tests/src/Tester.scala,line-23,offset=722
|
||||||
|
askTypeCompletion at source-/Users/dragos/workspace/git/scala/test/files/presentation/simple-tests/src/Tester.scala,line-105,offset=3041
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
[response] aksTypeCompletion at (12,39)
|
||||||
|
TypeMember(method $asInstanceOf,[T0]()T0,true,false,method any2stringadd)
|
||||||
|
TypeMember(method !=,(x$1: AnyRef)Boolean,true,false,method any2stringadd)
|
||||||
|
TypeMember(method !=,(x$1: Any)Boolean,true,false,method any2stringadd)
|
||||||
|
TypeMember(method ==,(x$1: AnyRef)Boolean,true,false,method any2stringadd)
|
||||||
|
TypeMember(method ==,(x$1: Any)Boolean,true,false,method any2stringadd)
|
||||||
|
TypeMember(method ##,()Int,true,false,method any2stringadd)
|
||||||
|
TypeMember(method $isInstanceOf,[T0]()Boolean,true,false,method any2stringadd)
|
||||||
|
TypeMember(method ->,[B](y: B)(scala.tools.nsc.reporters.StoreReporter, B),true,false,method any2ArrowAssoc)
|
||||||
|
TypeMember(method +,(other: String)java.lang.String,true,false,method any2stringadd)
|
||||||
|
TypeMember(method ?,[B](y: B)(scala.tools.nsc.reporters.StoreReporter, B),true,false,method any2ArrowAssoc)
|
||||||
|
TypeMember(constructor StoreReporter,()scala.tools.nsc.reporters.StoreReporter,true,false,<none>)
|
||||||
|
TypeMember(constructor StringAdd,(self: Any)scala.runtime.StringAdd,true,false,method any2stringadd)
|
||||||
|
TypeMember(constructor ArrowAssoc,(x: scala.tools.nsc.reporters.StoreReporter)ArrowAssoc[scala.tools.nsc.reporters.StoreReporter],true,false,method any2ArrowAssoc)
|
||||||
|
TypeMember(value ERROR,=> scala.tools.nsc.reporters.StoreReporter#Severity,true,true,<none>)
|
||||||
|
TypeMember(value INFO,=> scala.tools.nsc.reporters.StoreReporter#Severity,true,true,<none>)
|
||||||
|
TypeMember(class Info,scala.tools.nsc.reporters.StoreReporter#Info,true,false,<none>)
|
||||||
|
TypeMember(class Severity,scala.tools.nsc.reporters.StoreReporter#Severity,true,true,<none>)
|
||||||
|
TypeMember(value WARNING,=> scala.tools.nsc.reporters.StoreReporter#Severity,true,true,<none>)
|
||||||
|
TypeMember(method _truncationOK,=> Boolean,false,true,<none>)
|
||||||
|
TypeMember(method asInstanceOf,[T0]=> T0,true,true,<none>)
|
||||||
|
TypeMember(method cancelled,=> Boolean,true,true,<none>)
|
||||||
|
TypeMember(method clone,()java.lang.Object,false,true,<none>)
|
||||||
|
TypeMember(method comment,(pos: scala.tools.nsc.util.Position,msg: String)Unit,true,true,<none>)
|
||||||
|
TypeMember(method countAsString,(n: Int)String,true,true,<none>)
|
||||||
|
TypeMember(method countElementsAsString,(n: Int,elements: String)String,true,true,<none>)
|
||||||
|
TypeMember(method ensuring,(cond: (scala.tools.nsc.reporters.StoreReporter) => Boolean,msg: => Any)scala.tools.nsc.reporters.StoreReporter,true,false,method any2Ensuring)
|
||||||
|
TypeMember(method ensuring,(cond: (scala.tools.nsc.reporters.StoreReporter) => Boolean)scala.tools.nsc.reporters.StoreReporter,true,false,method any2Ensuring)
|
||||||
|
TypeMember(method ensuring,(cond: Boolean,msg: => Any)scala.tools.nsc.reporters.StoreReporter,true,false,method any2Ensuring)
|
||||||
|
TypeMember(method ensuring,(cond: Boolean)scala.tools.nsc.reporters.StoreReporter,true,false,method any2Ensuring)
|
||||||
|
TypeMember(method eq,(x$1: AnyRef)Boolean,true,true,<none>)
|
||||||
|
TypeMember(method equals,(x$1: Any)Boolean,true,true,<none>)
|
||||||
|
TypeMember(method error,(pos: scala.tools.nsc.util.Position,msg: String)Unit,true,true,<none>)
|
||||||
|
TypeMember(method finalize,()Unit,false,true,<none>)
|
||||||
|
TypeMember(method flush,()Unit,true,true,<none>)
|
||||||
|
TypeMember(method formatted,(fmtstr: String)String,true,false,method any2stringadd)
|
||||||
|
TypeMember(method getClass,()java.lang.Class[_],true,true,<none>)
|
||||||
|
TypeMember(method getSource,=> scala.tools.nsc.util.SourceFile,true,true,<none>)
|
||||||
|
TypeMember(method hasErrors,=> Boolean,true,true,<none>)
|
||||||
|
TypeMember(method hasWarnings,=> Boolean,true,true,<none>)
|
||||||
|
TypeMember(method hashCode,()Int,true,true,<none>)
|
||||||
|
TypeMember(method incompleteHandled,=> Boolean,true,true,<none>)
|
||||||
|
TypeMember(method incompleteInputError,=> (scala.tools.nsc.util.Position, String) => Unit,true,true,<none>)
|
||||||
|
TypeMember(method info,(pos: scala.tools.nsc.util.Position,msg: String,force: Boolean)Unit,true,true,<none>)
|
||||||
|
TypeMember(method info0,((pos: scala.tools.nsc.util.Position,msg: java.lang.String,severity: _5.Severity,force: Boolean)Unit) forSome { val _5: scala.tools.nsc.reporters.StoreReporter },false,false,<none>)
|
||||||
|
TypeMember(value infos,(=> scala.collection.mutable.HashSet[_3.Info]) forSome { val _3: scala.tools.nsc.reporters.StoreReporter },true,false,<none>)
|
||||||
|
TypeMember(value infos,scala.collection.mutable.HashSet[_4.Info] forSome { val _4: scala.tools.nsc.reporters.StoreReporter },false,false,<none>)
|
||||||
|
TypeMember(method isInstanceOf,[T0]=> Boolean,true,true,<none>)
|
||||||
|
TypeMember(method ne,(x$1: AnyRef)Boolean,true,true,<none>)
|
||||||
|
TypeMember(method notify,()Unit,true,true,<none>)
|
||||||
|
TypeMember(method notifyAll,()Unit,true,true,<none>)
|
||||||
|
TypeMember(method reset,()Unit,true,false,<none>)
|
||||||
|
TypeMember(value self,Any,false,false,method any2stringadd)
|
||||||
|
TypeMember(method setSource,(source: scala.tools.nsc.util.SourceFile)Unit,true,true,<none>)
|
||||||
|
TypeMember(object severity,object scala.tools.nsc.reporters.StoreReporter#severity,true,true,<none>)
|
||||||
|
TypeMember(method source,=> scala.tools.nsc.util.SourceFile,false,true,<none>)
|
||||||
|
TypeMember(method synchronized,[T0](x$1: T0)T0,true,true,<none>)
|
||||||
|
TypeMember(method toString,()java.lang.String,true,true,<none>)
|
||||||
|
TypeMember(method truncationOK,=> Boolean,true,true,<none>)
|
||||||
|
TypeMember(method wait,()Unit,true,true,<none>)
|
||||||
|
TypeMember(method wait,(x$1: Long,x$2: Int)Unit,true,true,<none>)
|
||||||
|
TypeMember(method wait,(x$1: Long)Unit,true,true,<none>)
|
||||||
|
TypeMember(method warning,(pos: scala.tools.nsc.util.Position,msg: String)Unit,true,true,<none>)
|
||||||
|
TypeMember(method withIncompleteHandler,[T](handler: (scala.tools.nsc.util.Position, String) => Unit)(thunk: => T)T,true,true,<none>)
|
||||||
|
TypeMember(method withSource,[A](src: scala.tools.nsc.util.SourceFile)(op: => A)A,true,true,<none>)
|
||||||
|
TypeMember(method withoutTruncating,[T](body: => T)T,true,true,<none>)
|
||||||
|
TypeMember(value x,=> scala.tools.nsc.reporters.StoreReporter,true,false,method any2ArrowAssoc)
|
||||||
|
TypeMember(value x,scala.tools.nsc.reporters.StoreReporter,false,false,method any2ArrowAssoc)
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
[response] aksTypeCompletion at (23,24)
|
||||||
|
TypeMember(method $asInstanceOf,[T0]()T0,true,false,method any2stringadd)
|
||||||
|
TypeMember(method !=,(x$1: AnyRef)Boolean,true,false,method any2stringadd)
|
||||||
|
TypeMember(method !=,(x$1: Any)Boolean,true,false,method any2stringadd)
|
||||||
|
TypeMember(method ==,(x$1: AnyRef)Boolean,true,false,method any2stringadd)
|
||||||
|
TypeMember(method ==,(x$1: Any)Boolean,true,false,method any2stringadd)
|
||||||
|
TypeMember(method ##,()Int,true,false,method any2stringadd)
|
||||||
|
TypeMember(method $isInstanceOf,[T0]()Boolean,true,false,method any2stringadd)
|
||||||
|
TypeMember(method ->,[B](y: B)(scala.tools.nsc.interactive.Response[U], B),true,false,method any2ArrowAssoc)
|
||||||
|
TypeMember(method +,(other: String)java.lang.String,true,false,method any2stringadd)
|
||||||
|
TypeMember(method ?,[B](y: B)(scala.tools.nsc.interactive.Response[U], B),true,false,method any2ArrowAssoc)
|
||||||
|
TypeMember(constructor Response,()scala.tools.nsc.interactive.Response[U],true,false,<none>)
|
||||||
|
TypeMember(constructor StringAdd,(self: Any)scala.runtime.StringAdd,true,false,method any2stringadd)
|
||||||
|
TypeMember(constructor ArrowAssoc,(x: scala.tools.nsc.interactive.Response[U])ArrowAssoc[scala.tools.nsc.interactive.Response[U]],true,false,method any2ArrowAssoc)
|
||||||
|
TypeMember(method asInstanceOf,[T0]=> T0,true,true,<none>)
|
||||||
|
TypeMember(method cancel,()Unit,true,false,<none>)
|
||||||
|
TypeMember(method cancelled,=> Boolean,false,false,<none>)
|
||||||
|
TypeMember(variable cancelled,Boolean,false,false,<none>)
|
||||||
|
TypeMember(method clear,()Unit,true,false,<none>)
|
||||||
|
TypeMember(method clone,()java.lang.Object,false,true,<none>)
|
||||||
|
TypeMember(method complete,=> Boolean,false,false,<none>)
|
||||||
|
TypeMember(variable complete,Boolean,false,false,<none>)
|
||||||
|
TypeMember(method data,=> Option[Either[U,Throwable]],false,false,<none>)
|
||||||
|
TypeMember(variable data,Option[Either[U,Throwable]],false,false,<none>)
|
||||||
|
TypeMember(method ensuring,(cond: (scala.tools.nsc.interactive.Response[U]) => Boolean,msg: => Any)scala.tools.nsc.interactive.Response[U],true,false,method any2Ensuring)
|
||||||
|
TypeMember(method ensuring,(cond: (scala.tools.nsc.interactive.Response[U]) => Boolean)scala.tools.nsc.interactive.Response[U],true,false,method any2Ensuring)
|
||||||
|
TypeMember(method ensuring,(cond: Boolean,msg: => Any)scala.tools.nsc.interactive.Response[U],true,false,method any2Ensuring)
|
||||||
|
TypeMember(method ensuring,(cond: Boolean)scala.tools.nsc.interactive.Response[U],true,false,method any2Ensuring)
|
||||||
|
TypeMember(method eq,(x$1: AnyRef)Boolean,true,true,<none>)
|
||||||
|
TypeMember(method equals,(x$1: Any)Boolean,true,true,<none>)
|
||||||
|
TypeMember(method finalize,()Unit,false,true,<none>)
|
||||||
|
TypeMember(method formatted,(fmtstr: String)String,true,false,method any2stringadd)
|
||||||
|
TypeMember(method get,=> Either[U,Throwable],true,false,<none>)
|
||||||
|
TypeMember(method get,(timeout: Long)Option[Either[U,Throwable]],true,false,<none>)
|
||||||
|
TypeMember(method getClass,()java.lang.Class[_],true,true,<none>)
|
||||||
|
TypeMember(method hashCode,()Int,true,true,<none>)
|
||||||
|
TypeMember(method isCancelled,=> Boolean,true,false,<none>)
|
||||||
|
TypeMember(method isComplete,=> Boolean,true,false,<none>)
|
||||||
|
TypeMember(method isInstanceOf,[T0]=> Boolean,true,true,<none>)
|
||||||
|
TypeMember(method ne,(x$1: AnyRef)Boolean,true,true,<none>)
|
||||||
|
TypeMember(method notify,()Unit,true,true,<none>)
|
||||||
|
TypeMember(method notifyAll,()Unit,true,true,<none>)
|
||||||
|
TypeMember(method raise,(exc: Throwable)Unit,true,false,<none>)
|
||||||
|
TypeMember(value self,Any,false,false,method any2stringadd)
|
||||||
|
TypeMember(method set,(x: U)Unit,true,false,<none>)
|
||||||
|
TypeMember(method setProvisionally,(x: U)Unit,true,false,<none>)
|
||||||
|
TypeMember(method synchronized,[T0](x$1: T0)T0,true,true,<none>)
|
||||||
|
TypeMember(method toString,()java.lang.String,true,true,<none>)
|
||||||
|
TypeMember(method wait,()Unit,true,true,<none>)
|
||||||
|
TypeMember(method wait,(x$1: Long,x$2: Int)Unit,true,true,<none>)
|
||||||
|
TypeMember(method wait,(x$1: Long)Unit,true,true,<none>)
|
||||||
|
TypeMember(value x,=> scala.tools.nsc.interactive.Response[U],true,false,method any2ArrowAssoc)
|
||||||
|
TypeMember(value x,scala.tools.nsc.interactive.Response[U],false,false,method any2ArrowAssoc)
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
[response] aksTypeCompletion at (105,29)
|
||||||
|
TypeMember(method $asInstanceOf,[T0]()T0,true,false,method any2stringadd)
|
||||||
|
TypeMember(method !=,(x$1: AnyRef)Boolean,true,false,method any2stringadd)
|
||||||
|
TypeMember(method !=,(x$1: Any)Boolean,true,false,method any2stringadd)
|
||||||
|
TypeMember(method ==,(x$1: AnyRef)Boolean,true,false,method any2stringadd)
|
||||||
|
TypeMember(method ==,(x$1: Any)Boolean,true,false,method any2stringadd)
|
||||||
|
TypeMember(method ##,()Int,true,false,method any2stringadd)
|
||||||
|
TypeMember(method $isInstanceOf,[T0]()Boolean,true,false,method any2stringadd)
|
||||||
|
TypeMember(method ->,[B](y: B)(scala.tools.nsc.util.SourceFile, B),true,false,method any2ArrowAssoc)
|
||||||
|
TypeMember(method +,(other: String)java.lang.String,true,false,method any2stringadd)
|
||||||
|
TypeMember(method ?,[B](y: B)(scala.tools.nsc.util.SourceFile, B),true,false,method any2ArrowAssoc)
|
||||||
|
TypeMember(constructor SourceFile,()scala.tools.nsc.util.SourceFile,true,false,<none>)
|
||||||
|
TypeMember(constructor StringAdd,(self: Any)scala.runtime.StringAdd,true,false,method any2stringadd)
|
||||||
|
TypeMember(constructor ArrowAssoc,(x: scala.tools.nsc.util.SourceFile)ArrowAssoc[scala.tools.nsc.util.SourceFile],true,false,method any2ArrowAssoc)
|
||||||
|
TypeMember(method asInstanceOf,[T0]=> T0,true,true,<none>)
|
||||||
|
TypeMember(method beginsWith,(offset: Int,text: String)Boolean,true,false,<none>)
|
||||||
|
TypeMember(method clone,()java.lang.Object,false,true,<none>)
|
||||||
|
TypeMember(method content,=> Array[Char],true,false,<none>)
|
||||||
|
TypeMember(method dbg,(offset: Int)java.lang.String,true,false,<none>)
|
||||||
|
TypeMember(method ensuring,(cond: (scala.tools.nsc.util.SourceFile) => Boolean,msg: => Any)scala.tools.nsc.util.SourceFile,true,false,method any2Ensuring)
|
||||||
|
TypeMember(method ensuring,(cond: (scala.tools.nsc.util.SourceFile) => Boolean)scala.tools.nsc.util.SourceFile,true,false,method any2Ensuring)
|
||||||
|
TypeMember(method ensuring,(cond: Boolean,msg: => Any)scala.tools.nsc.util.SourceFile,true,false,method any2Ensuring)
|
||||||
|
TypeMember(method ensuring,(cond: Boolean)scala.tools.nsc.util.SourceFile,true,false,method any2Ensuring)
|
||||||
|
TypeMember(method eq,(x$1: AnyRef)Boolean,true,true,<none>)
|
||||||
|
TypeMember(method equals,(x$1: Any)Boolean,true,true,<none>)
|
||||||
|
TypeMember(method file,=> scala.tools.nsc.io.AbstractFile,true,false,<none>)
|
||||||
|
TypeMember(method finalize,()Unit,false,true,<none>)
|
||||||
|
TypeMember(method formatted,(fmtstr: String)String,true,false,method any2stringadd)
|
||||||
|
TypeMember(method getClass,()java.lang.Class[_],true,true,<none>)
|
||||||
|
TypeMember(method hashCode,()Int,true,true,<none>)
|
||||||
|
TypeMember(method identifier,(pos: scala.tools.nsc.util.Position,compiler: scala.tools.nsc.Global)Option[String],true,false,<none>)
|
||||||
|
TypeMember(method isInstanceOf,[T0]=> Boolean,true,true,<none>)
|
||||||
|
TypeMember(method isLineBreak,(idx: Int)Boolean,true,false,<none>)
|
||||||
|
TypeMember(method isSelfContained,=> Boolean,true,false,<none>)
|
||||||
|
TypeMember(method length,=> Int,true,false,<none>)
|
||||||
|
TypeMember(method lineToOffset,(index: Int)Int,true,false,<none>)
|
||||||
|
TypeMember(method lineToString,(index: Int)String,true,false,<none>)
|
||||||
|
TypeMember(method ne,(x$1: AnyRef)Boolean,true,true,<none>)
|
||||||
|
TypeMember(method notify,()Unit,true,true,<none>)
|
||||||
|
TypeMember(method notifyAll,()Unit,true,true,<none>)
|
||||||
|
TypeMember(method offsetToLine,(offset: Int)Int,true,false,<none>)
|
||||||
|
TypeMember(method path,=> String,true,false,<none>)
|
||||||
|
TypeMember(method position,(offset: Int)scala.tools.nsc.util.Position,true,false,<none>)
|
||||||
|
TypeMember(method position,(line: Int,column: Int)scala.tools.nsc.util.Position,true,false,<none>)
|
||||||
|
TypeMember(method positionInUltimateSource,(position: scala.tools.nsc.util.Position)scala.tools.nsc.util.Position,true,false,<none>)
|
||||||
|
TypeMember(value self,Any,false,false,method any2stringadd)
|
||||||
|
TypeMember(method skipWhitespace,(offset: Int)Int,true,false,<none>)
|
||||||
|
TypeMember(method synchronized,[T0](x$1: T0)T0,true,true,<none>)
|
||||||
|
TypeMember(method toString,()String,true,false,<none>)
|
||||||
|
TypeMember(method wait,()Unit,true,true,<none>)
|
||||||
|
TypeMember(method wait,(x$1: Long,x$2: Int)Unit,true,true,<none>)
|
||||||
|
TypeMember(method wait,(x$1: Long)Unit,true,true,<none>)
|
||||||
|
TypeMember(value x,=> scala.tools.nsc.util.SourceFile,true,false,method any2ArrowAssoc)
|
||||||
|
TypeMember(value x,scala.tools.nsc.util.SourceFile,false,false,method any2ArrowAssoc)
|
||||||
|
askTypeAt at source-/Users/dragos/workspace/git/scala/test/files/presentation/simple-tests/src/Tester.scala,line-12,offset=243
|
||||||
|
askTypeAt at source-/Users/dragos/workspace/git/scala/test/files/presentation/simple-tests/src/Tester.scala,line-13,offset=288
|
||||||
|
[response] askTypeAt at (12,14)
|
||||||
|
private[this] val reporter: scala.tools.nsc.reporters.StoreReporter = new reporters.StoreReporter()
|
||||||
|
[response] askTypeAt at (13,14)
|
||||||
|
private[this] val compiler: scala.tools.nsc.interactive.Global = new Global(Tester.this.settings, Tester.this.reporter)
|
|
@ -0,0 +1,9 @@
|
||||||
|
import scala.tools.nsc.interactive.tests._
|
||||||
|
|
||||||
|
/** Simple test that shows how to use the InteractiveTest class. It uses the
|
||||||
|
* inherited runTest method that runs completion and typedAt tests on all
|
||||||
|
* sources found under src/
|
||||||
|
*/
|
||||||
|
object Test extends InteractiveTest {
|
||||||
|
override val runRandomTests = false
|
||||||
|
}
|
|
@ -0,0 +1,204 @@
|
||||||
|
package scala.tools.nsc
|
||||||
|
package interactive
|
||||||
|
package tests
|
||||||
|
|
||||||
|
import util._
|
||||||
|
import reporters._
|
||||||
|
import io.AbstractFile
|
||||||
|
import collection.mutable.ArrayBuffer
|
||||||
|
|
||||||
|
class Tester(ntests: Int, inputs: Array[SourceFile], settings: Settings) {
|
||||||
|
|
||||||
|
val reporter/*?*/ = new StoreReporter/*!*/
|
||||||
|
val compiler/*?*/ = new Global(settings, reporter)
|
||||||
|
|
||||||
|
def askAndListen[T, U](msg: String, arg: T, op: (T, Response[U]) => Unit) {
|
||||||
|
if (settings.verbose.value) print(msg+" "+arg+": ")
|
||||||
|
val TIMEOUT = 10 // ms
|
||||||
|
val limit = System.currentTimeMillis() + randomDelayMillis
|
||||||
|
val res = new Response[U]
|
||||||
|
op(arg, res)
|
||||||
|
while (!res.isComplete && !res.isCancelled) {
|
||||||
|
if (System.currentTimeMillis() > limit) {
|
||||||
|
print("c"); res./*!*/cancel()
|
||||||
|
} else res.get(TIMEOUT) match {
|
||||||
|
case Some(Left(t)) =>
|
||||||
|
/**/
|
||||||
|
if (settings.verbose.value) println(t)
|
||||||
|
case Some(Right(ex)) =>
|
||||||
|
ex.printStackTrace()
|
||||||
|
println(ex)
|
||||||
|
case None =>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def askReload(sfs: SourceFile*) = askAndListen("reload", sfs.toList, compiler.askReload)
|
||||||
|
def askTypeAt(pos: Position) = askAndListen("type at", pos, compiler.askTypeAt)
|
||||||
|
def askTypeCompletion(pos: Position) = askAndListen("type at", pos, compiler.askTypeCompletion)
|
||||||
|
def askScopeCompletion(pos: Position) = askAndListen("type at", pos, compiler.askScopeCompletion)
|
||||||
|
|
||||||
|
val rand = new java.util.Random()
|
||||||
|
|
||||||
|
private def randomInverse(n: Int) = n / (rand.nextInt(n) + 1)
|
||||||
|
|
||||||
|
private def randomDecreasing(n: Int) = {
|
||||||
|
var r = rand.nextInt((1 to n).sum)
|
||||||
|
var limit = n
|
||||||
|
var result = 0
|
||||||
|
while (r > limit) {
|
||||||
|
result += 1
|
||||||
|
r -= limit
|
||||||
|
limit -= 1
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
def randomSourceFileIdx() = rand.nextInt(inputs.length)
|
||||||
|
|
||||||
|
def randomBatchesPerSourceFile(): Int = randomDecreasing(100)
|
||||||
|
|
||||||
|
def randomChangesPerBatch(): Int = randomInverse(50)
|
||||||
|
|
||||||
|
def randomPositionIn(sf: SourceFile) = rand.nextInt(sf.content.length)
|
||||||
|
|
||||||
|
def randomNumChars() = randomInverse(100)
|
||||||
|
|
||||||
|
def randomDelayMillis = randomInverse(10000)
|
||||||
|
|
||||||
|
class Change(sfidx: Int, start: Int, nchars: Int, toLeft: Boolean) {
|
||||||
|
|
||||||
|
private var pos = start
|
||||||
|
private var deleted: List[Char] = List()
|
||||||
|
|
||||||
|
override def toString =
|
||||||
|
"In "+inputs(sfidx)+" at "+start+" take "+nchars+" to "+
|
||||||
|
(if (toLeft) "left" else "right")
|
||||||
|
|
||||||
|
def deleteOne() {
|
||||||
|
val sf = inputs(sfidx)
|
||||||
|
deleted = sf.content(pos) :: deleted
|
||||||
|
val sf1 = new BatchSourceFile(sf.file, sf.content.take(pos) ++ sf.content.drop(pos + 1))
|
||||||
|
inputs(sfidx) = sf1
|
||||||
|
askReload(sf1)
|
||||||
|
}
|
||||||
|
|
||||||
|
def deleteAll() {
|
||||||
|
print("/"+nchars)
|
||||||
|
for (i <- 0 until nchars) {
|
||||||
|
if (toLeft) {
|
||||||
|
if (pos > 0 && pos <= inputs(sfidx).length) {
|
||||||
|
pos -= 1
|
||||||
|
deleteOne()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (pos < inputs(sfidx).length) {
|
||||||
|
deleteOne()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def insertAll() {
|
||||||
|
for (chr <- if (toLeft) deleted else deleted.reverse) {
|
||||||
|
val sf = inputs(sfidx)
|
||||||
|
val (pre, post) = sf./*!*/content splitAt pos
|
||||||
|
pos += 1
|
||||||
|
val sf1 = new BatchSourceFile(sf.file, pre ++ (chr +: post))
|
||||||
|
inputs(sfidx) = sf1
|
||||||
|
askReload(sf1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val testComment = "/**/"
|
||||||
|
|
||||||
|
def testFileChanges(sfidx: Int) = {
|
||||||
|
lazy val testPositions: Seq[Int] = {
|
||||||
|
val sf = inputs(sfidx)
|
||||||
|
val buf = new ArrayBuffer[Int]
|
||||||
|
var pos = sf.content.indexOfSlice(testComment)
|
||||||
|
while (pos > 0) {
|
||||||
|
buf += pos
|
||||||
|
pos = sf.content.indexOfSlice(testComment, pos + 1)
|
||||||
|
}
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
def otherTest() {
|
||||||
|
if (testPositions.nonEmpty) {
|
||||||
|
val pos = new OffsetPosition(inputs(sfidx), rand.nextInt(testPositions.length))
|
||||||
|
rand.nextInt(3) match {
|
||||||
|
case 0 => askTypeAt(pos)
|
||||||
|
case 1 => askTypeCompletion(pos)
|
||||||
|
case 2 => askScopeCompletion(pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i <- 0 until randomBatchesPerSourceFile()) {
|
||||||
|
val changes = Vector.fill(/**/randomChangesPerBatch()) {
|
||||||
|
/**/
|
||||||
|
new Change(sfidx, randomPositionIn(inputs(sfidx)), randomNumChars(), rand.nextBoolean())
|
||||||
|
}
|
||||||
|
doTest(sfidx, changes, testPositions, otherTest) match {
|
||||||
|
case Some(errortrace) =>
|
||||||
|
println(errortrace)
|
||||||
|
minimize(errortrace)
|
||||||
|
case None =>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def doTest(sfidx: Int, changes: Seq[Change], testPositions: Seq[Int], otherTest: () => Unit): Option[ErrorTrace] = {
|
||||||
|
print("new round with "+changes.length+" changes:")
|
||||||
|
changes foreach (_.deleteAll())
|
||||||
|
otherTest()
|
||||||
|
def errorCount() = compiler.ask(() => reporter.ERROR.count)
|
||||||
|
// println("\nhalf test round: "+errorCount())
|
||||||
|
changes.view.reverse foreach (_.insertAll())
|
||||||
|
otherTest()
|
||||||
|
println("done test round: "+errorCount())
|
||||||
|
if (errorCount() != 0)
|
||||||
|
Some(ErrorTrace(sfidx, changes, reporter.infos, inputs(sfidx).content))
|
||||||
|
else
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
case class ErrorTrace(
|
||||||
|
sfidx: Int, changes: Seq[Change], infos: collection.Set[reporter.Info], content: Array[Char]) {
|
||||||
|
override def toString =
|
||||||
|
"Sourcefile: "+inputs(sfidx)+
|
||||||
|
"\nChanges:\n "+changes.mkString("\n ")+
|
||||||
|
"\nErrors:\n "+infos.mkString("\n ")+
|
||||||
|
"\nContents:\n"+content.mkString
|
||||||
|
}
|
||||||
|
|
||||||
|
def minimize(etrace: ErrorTrace) {}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
def run() {
|
||||||
|
askReload(inputs: _*)
|
||||||
|
for (i <- 0 until ntests)
|
||||||
|
testFileChanges(randomSourceFileIdx())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A program to do presentation compiler stress tests.
|
||||||
|
* Usage:
|
||||||
|
*
|
||||||
|
* scala scala.tools.nsc.interactive.test.Tester <n> <files>
|
||||||
|
*
|
||||||
|
* where <n> is the number os tests to be run and <files> is the set of files to test.
|
||||||
|
* This will do random deletions and re-insertions in any of the files.
|
||||||
|
* At places where an empty comment /**/ appears it will in addition randomly
|
||||||
|
* do ask-types, type-completions, or scope-completions.
|
||||||
|
*/
|
||||||
|
object Tester {
|
||||||
|
def main(args: Array[String]) {
|
||||||
|
val settings = new Settings()
|
||||||
|
val (_, filenames) = settings.processArguments(args.toList.tail, true)
|
||||||
|
println("filenames = "+filenames)
|
||||||
|
val files = filenames.toArray map (str => new BatchSourceFile(AbstractFile.getFile(str)): SourceFile)
|
||||||
|
new Tester(args(0).toInt, files, settings).run()
|
||||||
|
sys.exit(0)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue