diff options
64 files changed, 662 insertions, 1567 deletions
@@ -137,6 +137,7 @@ TODO: <property name="build-quick.dir" value="${build.dir}/quick"/> <property name="build-pack.dir" value="${build.dir}/pack"/> <property name="build-osgi.dir" value="${build.dir}/osgi"/> + <property name="build-junit.dir" value="${build.dir}/junit"/> <property name="build-strap.dir" value="${build.dir}/strap"/> <property name="build-docs.dir" value="${build.dir}/scaladoc"/> <property name="build-sbt.dir" value="${build.dir}/sbt-interface"/> @@ -144,6 +145,9 @@ TODO: <property name="test.osgi.src" value="${partest.dir}/osgi/src"/> <property name="test.osgi.classes" value="${build-osgi.dir}/classes"/> + <property name="test.junit.src" value="${partest.dir}/junit"/> + <property name="test.junit.classes" value="${build-junit.dir}/classes"/> + <property name="dists.dir" value="${basedir}/dists"/> <property name="copyright.string" value="Copyright 2002-2013, LAMP/EPFL"/> @@ -208,6 +212,12 @@ TODO: <dependency groupId="biz.aQute" artifactId="bnd" version="1.50.0"/> </artifact:dependencies> + <!-- JUnit --> + <property name="junit.version" value="4.10"/> + <artifact:dependencies pathId="junit.classpath" filesetId="junit.fileset"> + <dependency groupId="junit" artifactId="junit" version="${junit.version}"/> + </artifact:dependencies> + <!-- Pax runner --> <property name="pax.exam.version" value="2.5.0"/> <artifact:dependencies pathId="pax.exam.classpath" filesetId="pax.exam.fileset"> @@ -218,10 +228,11 @@ TODO: <dependency groupId="org.ops4j.pax.swissbox" artifactId="pax-swissbox-framework" version="1.5.1"/> <dependency groupId="ch.qos.logback" artifactId="logback-core" version="0.9.20"/> <dependency groupId="ch.qos.logback" artifactId="logback-classic" version="0.9.20"/> - <dependency groupId="junit" artifactId="junit" version="4.10"/> + <dependency groupId="junit" artifactId="junit" version="${junit.version}"/> <dependency groupId="org.apache.felix" artifactId="org.apache.felix.framework" version="3.2.2"/> </artifact:dependencies> + <artifact:dependencies pathId="partest.extras.classpath" filesetId="partest.extras.fileset" versionsId="partest.extras.versions"> <dependency groupId="com.googlecode.java-diff-utils" artifactId="diffutils" version="1.3.0"/> <dependency groupId="org.scala-tools.testing" artifactId="test-interface" version="0.5" /> @@ -673,6 +684,12 @@ TODO: </path> --> + <path id="test.junit.compiler.build.path"> + <pathelement location="${test.junit.classes}"/> + <path refid="quick.compiler.build.path"/> + <path refid="junit.classpath"/> + </path> + <path id="test.osgi.compiler.build.path"> <pathelement location="${test.osgi.classes}"/> <pathelement location="${build-osgi.dir}/org.scala-lang.scala-library.jar"/> @@ -1437,6 +1454,45 @@ TODO: <stopwatch name="quick.sbt-interface.timer" action="total"/> </target> + <target name="test.junit.init" depends="quick.done"> + <uptodate property="test.junit.available" targetfile="${build-junit.dir}/test-compile.complete"> + <srcfiles dir="${test.junit.src}"> + <include name="**/*.scala"/> + </srcfiles> + </uptodate> + </target> + + <target name="test.junit.comp" depends="test.junit.init, quick.done" unless="test.junit.available"> + <stopwatch name="test.junit.compiler.timer"/> + <mkdir dir="${test.junit.classes}"/> + <scalacfork + destdir="${test.junit.classes}" + compilerpathref="quick.compiler.path" + params="${scalac.args.quick}" + srcdir="${test.junit.src}" + jvmargs="${scalacfork.jvmargs}"> + <include name="**/*.scala"/> + <compilationpath refid="test.junit.compiler.build.path"/> + </scalacfork> + <touch file="${build-junit.dir}/test-compile.complete" verbose="no"/> + <stopwatch name="test.junit.compiler.timer" action="total"/> + </target> + + <target name="test.junit" depends="test.junit.comp"> + <stopwatch name="test.junit.timer"/> + <mkdir dir="${test.junit.classes}"/> + <junit fork="yes" haltonfailure="yes" showoutput="yes" printsummary="on"> + <classpath refid="test.junit.compiler.build.path"/> + <batchtest fork="yes" todir="${build-junit.dir}"> + <fileset dir="${test.junit.classes}"> + <include name="**/*Test.class"/> + </fileset> + </batchtest> + <formatter type="plain"/> + </junit> + <stopwatch name="test.junit.timer" action="total"/> + </target> + <!-- See test/build-partest.xml for the macro(s) being used here. --> <target name="test.suite" depends="pack.done"> @@ -1467,7 +1523,7 @@ TODO: <!-- for use in PR validation, where stability is rarely broken, so we're going to use starr for locker, and skip test.stability (which requires locker == quick) --> - <target name="test.core" depends="test.osgi, test.sbt, test.bc, test.interactive, test.continuations.suite, test.scaladoc, test.suite"/> + <target name="test.core" depends="test.osgi, test.sbt, test.bc, test.junit, test.interactive, test.continuations.suite, test.scaladoc, test.suite"/> <target name="test.done" depends="test.core, test.stability"/> <!-- =========================================================================== diff --git a/gitignore.SAMPLE b/gitignore.SAMPLE index 483ad4caca..7114225a4a 100644 --- a/gitignore.SAMPLE +++ b/gitignore.SAMPLE @@ -5,13 +5,6 @@ *.jar *~ -#sbt -/project/target/ -/project/project/target - -/target/ -/src/jline/target/ - # target directories for ant build /build/ /dists/ diff --git a/project/Build.scala b/project/Build.scala deleted file mode 100644 index efa8a7a038..0000000000 --- a/project/Build.scala +++ /dev/null @@ -1,334 +0,0 @@ -import sbt._ -import Keys._ -import partest._ -import ScalaBuildKeys._ -import Release._ - - -object ScalaBuild extends Build with Layers with Packaging with Testing { - - // Build wide settings: - override lazy val settings = super.settings ++ Versions.settings ++ Seq( - autoScalaLibrary := false, - resolvers += Resolver.url( - "Typesafe nightlies", - url("https://typesafe.artifactoryonline.com/typesafe/ivy-snapshots/") - )(Resolver.ivyStylePatterns), - resolvers ++= Seq( - "junit interface repo" at "https://repository.jboss.org/nexus/content/repositories/scala-tools-releases", - ScalaToolsSnapshots - ), - organization := "org.scala-lang", - version <<= Versions.mavenVersion, - pomExtra := epflPomExtra - ) - - // Collections of projects to run 'compile' on. - lazy val compiledProjects = Seq(quickLib, quickComp, continuationsLibrary, actors, swing, forkjoin) - // Collection of projects to 'package' and 'publish' together. - lazy val packagedBinaryProjects = Seq(scalaLibrary, scalaCompiler, swing, actors, continuationsPlugin, jline, scalap) - lazy val partestRunProjects = Seq(testsuite, continuationsTestsuite) - - private def epflPomExtra = ( - <xml:group> - <inceptionYear>2002</inceptionYear> - <licenses> - <license> - <name>BSD-like</name> - <url>http://www.scala-lang.org/downloads/license.html</url> - </license> - </licenses> - <scm> - <connection>scm:git:git://github.com/scala/scala.git</connection> - </scm> - <issueManagement> - <system>jira</system> - <url>http://issues.scala-lang.org</url> - </issueManagement> - </xml:group> - ) - - // Settings used to make sure publishing goes smoothly. - def publishSettings: Seq[Setting[_]] = Seq( - ivyScala ~= ((is: Option[IvyScala]) => is.map(_.copy(checkExplicit = false))), - pomIncludeRepository := (_ => false), - publishMavenStyle := true, - makePomConfiguration <<= makePomConfiguration apply (_.copy(configurations = Some(Seq(Compile, Default)))), - pomExtra := epflPomExtra - ) - - // Settings for root project. These are aggregate tasks against the rest of the build. - def projectSettings: Seq[Setting[_]] = publishSettings ++ Seq( - doc in Compile <<= (doc in documentation in Compile).identity, - // These next two aggregate commands on several projects and return results that are to be ignored by remaining tasks. - compile in Compile <<= compiledProjects.map(p => compile in p in Compile).join.map(_.head), - // TODO - just clean target? i.e. target map IO.deleteRecursively - clean <<= (compiledProjects ++ partestRunProjects).map(p => clean in p).dependOn, - packageBin in Compile <<= packagedBinaryProjects.map(p => packageBin in p in Compile).join.map(_.head), - // TODO - Make sure scalaLibrary has packageDoc + packageSrc from documentation attached... - publish <<= packagedBinaryProjects.map(p => publish in p).join.map(_.head), - publishLocal <<= packagedBinaryProjects.map(p => publishLocal in p).join.map(_.head), - packageDoc in Compile <<= (packageDoc in documentation in Compile).identity, - packageSrc in Compile <<= (packageSrc in documentation in Compile).identity, - test in Test <<= (runPartest in testsuite, runPartest in continuationsTestsuite, checkSame in testsuite) map { (a,b,c) => () }, - lockerLock <<= (lockFile in lockerLib, lockFile in lockerComp, compile in Compile in lockerLib, compile in Compile in lockerComp) map { (lib, comp, _, _) => - Seq(lib,comp).foreach(f => IO.touch(f)) - }, - lockerUnlock <<= (lockFile in lockerLib, lockFile in lockerComp) map { (lib, comp) => - Seq(lib,comp).foreach(IO.delete) - }, - genBinQuick <<= (genBinQuick in scaladist).identity, - makeDist <<= (makeDist in scaladist).identity, - makeExplodedDist <<= (makeExplodedDist in scaladist).identity, - // Note: We override unmanagedSources so that ~ compile will look at all these sources, then run our aggregated compile... - unmanagedSourceDirectories in Compile <<= baseDirectory apply (_ / "src") apply { dir => - Seq("library/scala","actors","compiler","swing","continuations/library","forkjoin") map (dir / _) - }, - // TODO - Make exported products == makeDist so we can use this when creating a *real* distribution. - commands += Release.pushStarr - ) - // Note: Root project is determined by lowest-alphabetical project that has baseDirectory as file("."). we use aaa_ to 'win'. - lazy val aaa_root = Project("scala", file(".")) settings(projectSettings: _*) settings(ShaResolve.settings: _*) - - // External dependencies used for various projects - lazy val externalDeps: Setting[_] = libraryDependencies <<= (sbtVersion)(v => - Seq( - "org.apache.ant" % "ant" % "1.8.2", - "org.scala-sbt" % "compiler-interface" % v % "provided" - ) - ) - - def fixArtifactSrc(dir: File, name: String) = name match { - case x if x startsWith "scala-" => dir / "src" / (name drop 6) - case x => dir / "src" / name - } - - // These are setting overrides for most artifacts in the Scala build file. - def settingOverrides: Seq[Setting[_]] = publishSettings ++ Seq( - crossPaths := false, - autoScalaLibrary := false, - // Work around a bug where scala-library (and forkjoin) is put on classpath for analysis. - classpathOptions := ClasspathOptions.manual, - publishArtifact in packageDoc := false, - publishArtifact in packageSrc := false, - target <<= (baseDirectory, name) apply (_ / "target" / _), - (classDirectory in Compile) <<= target(_ / "classes"), - javacOptions ++= Seq("-target", "1.5", "-source", "1.5"), - scalaSource in Compile <<= (baseDirectory, name) apply fixArtifactSrc, - javaSource in Compile <<= (baseDirectory, name) apply fixArtifactSrc, - unmanagedJars in Compile := Seq(), - // Most libs in the compiler use this order to build. - compileOrder in Compile := CompileOrder.JavaThenScala, - lockFile <<= target(_ / "compile.lock"), - skip in Compile <<= lockFile map (_.exists), - lock <<= lockFile map (f => IO.touch(f)), - unlock <<= lockFile map IO.delete - ) - - // -------------------------------------------------------------- - // Libraries used by Scalac that change infrequently - // (or hopefully so). - // -------------------------------------------------------------- - - // Jline nested project. Compile this sucker once and be done. - lazy val jline = Project("jline", file("src/jline")) - // Our wrapped version of asm. - lazy val asm = Project("asm", file(".")) settings(settingOverrides : _*) - // Forkjoin backport - lazy val forkjoin = Project("forkjoin", file(".")) settings(settingOverrides : _*) - - // -------------------------------------------------------------- - // The magic kingdom. - // Layered compilation of Scala. - // Stable Reference -> Locker ('Lockable' dev version) -> Quick -> Strap (Binary compatibility testing) - // -------------------------------------------------------------- - - // Need a report on this... - // TODO - Resolve STARR from a repo.. - lazy val STARR = scalaInstance <<= (appConfiguration, ShaResolve.pullBinaryLibs in ThisBuild) map { (app, _) => - val launcher = app.provider.scalaProvider.launcher - val library = file("lib/scala-library.jar") - val compiler = file("lib/scala-compiler.jar") - val libJars = (file("lib") * "*.jar").get filterNot Set(library, compiler) - ScalaInstance("starr", library, compiler, launcher, libJars: _*) - } - - // Locker is a lockable Scala compiler that can be built of 'current' source to perform rapid development. - lazy val (lockerLib, lockerReflect, lockerComp) = makeLayer("locker", STARR, autoLock = true) - lazy val locker = Project("locker", file(".")) aggregate(lockerLib, lockerReflect, lockerComp) - - // Quick is the general purpose project layer for the Scala compiler. - lazy val (quickLib, quickReflect, quickComp) = makeLayer("quick", makeScalaReference("locker", lockerLib, lockerReflect, lockerComp)) - lazy val quick = Project("quick", file(".")) aggregate(quickLib, quickReflect, quickComp) - - // Reference to quick scala instance. - lazy val quickScalaInstance = makeScalaReference("quick", quickLib, quickReflect, quickComp) - def quickScalaLibraryDependency = unmanagedClasspath in Compile <++= (exportedProducts in quickLib in Compile).identity - def quickScalaReflectDependency = unmanagedClasspath in Compile <++= (exportedProducts in quickReflect in Compile).identity - def quickScalaCompilerDependency = unmanagedClasspath in Compile <++= (exportedProducts in quickComp in Compile).identity - - // Strapp is used to test binary 'sameness' between things built with locker and things built with quick. - lazy val (strappLib, strappReflect, strappComp) = makeLayer("strapp", quickScalaInstance) - - // -------------------------------------------------------------- - // Projects dependent on layered compilation (quick) - // -------------------------------------------------------------- - def addCheaterDependency(projectName: String): Setting[_] = - pomPostProcess <<= (version, organization, pomPostProcess) apply { (v,o,k) => - val dependency: scala.xml.Node = - <dependency> - <groupId>{o}</groupId> - <artifactid>{projectName}</artifactid> - <version>{v}</version> - </dependency> - def fixDependencies(node: scala.xml.Node): scala.xml.Node = node match { - case <dependencies>{nested@_*}</dependencies> => <dependencies>{dependency}{nested}</dependencies> - case x => x - } - // This is a hack to get around issues where \ and \\ don't work if any of the children are `scala.xml.Group`. - def hasDependencies(root: scala.xml.Node): Boolean = - (root.child collectFirst { - case n: scala.xml.Elem if n.label == "dependencies" => n - } isEmpty) - // TODO - Keep namespace on project... - k andThen { - case n @ <project>{ nested@_*}</project> if hasDependencies(n) => - <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0">{nested}<dependencies>{dependency}</dependencies></project> - case <project>{ nested@_*}</project> => - <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0">{ nested map fixDependencies }</project> - } - } - - // TODO - in sabbus, these all use locker to build... I think tihs way is better, but let's farm this idea around. - lazy val dependentProjectSettings = settingOverrides ++ Seq(quickScalaInstance, quickScalaLibraryDependency, addCheaterDependency("scala-library")) - lazy val actors = Project("scala-actors", file(".")) settings(dependentProjectSettings:_*) dependsOn(forkjoin % "provided") - lazy val swing = Project("scala-swing", file(".")) settings(dependentProjectSettings:_*) dependsOn(actors % "provided") - // This project will generate man pages (in man1 and html) for scala. - lazy val manmakerSettings: Seq[Setting[_]] = dependentProjectSettings :+ externalDeps - lazy val manmaker = Project("manual", file(".")) settings(manmakerSettings:_*) - - // Things that compile against the compiler. - lazy val compilerDependentProjectSettings = dependentProjectSettings ++ Seq(quickScalaReflectDependency, quickScalaCompilerDependency, addCheaterDependency("scala-compiler")) - - lazy val scalacheck = Project("scalacheck", file(".")) settings(compilerDependentProjectSettings:_*) dependsOn(actors % "provided") - lazy val partestSettings = compilerDependentProjectSettings :+ externalDeps - lazy val partest = Project("partest", file(".")) settings(partestSettings:_*) dependsOn(actors,forkjoin,scalap,asm) - lazy val scalapSettings = compilerDependentProjectSettings ++ Seq( - name := "scalap", - exportJars := true - ) - lazy val scalap = Project("scalap", file(".")) settings(scalapSettings:_*) - - // -------------------------------------------------------------- - // Continuations plugin + library - // -------------------------------------------------------------- - lazy val continuationsPluginSettings = compilerDependentProjectSettings ++ Seq( - scalaSource in Compile <<= baseDirectory(_ / "src/continuations/plugin/"), - resourceDirectory in Compile <<= baseDirectory(_ / "src/continuations/plugin/"), - exportJars := true, - name := "continuations" // Note: This artifact is directly exported. - - ) - lazy val continuationsPlugin = Project("continuations-plugin", file(".")) settings(continuationsPluginSettings:_*) - lazy val continuationsLibrarySettings = dependentProjectSettings ++ Seq( - scalaSource in Compile <<= baseDirectory(_ / "src/continuations/library/"), - scalacOptions in Compile <++= (exportedProducts in Compile in continuationsPlugin) map { - case Seq(cpDir) => Seq("-Xplugin-require:continuations", "-P:continuations:enable", "-Xplugin:"+cpDir.data.getAbsolutePath) - } - ) - lazy val continuationsLibrary = Project("continuations-library", file(".")) settings(continuationsLibrarySettings:_*) - - // TODO - OSGi Manifest - - // -------------------------------------------------------------- - // Real Library Artifact - // -------------------------------------------------------------- - val allSubpathsCopy = (dir: File) => (dir.*** --- dir) x (relativeTo(dir)|flat) - def productTaskToMapping(products : Seq[File]) = products flatMap { p => allSubpathsCopy(p) } - lazy val packageScalaLibBinTask = Seq(quickLib, continuationsLibrary, forkjoin).map(p => products in p in Compile).join.map(_.flatten).map(productTaskToMapping) - lazy val scalaLibArtifactSettings: Seq[Setting[_]] = inConfig(Compile)(Defaults.packageTasks(packageBin, packageScalaLibBinTask)) ++ Seq( - name := "scala-library", - crossPaths := false, - exportJars := true, - autoScalaLibrary := false, - unmanagedJars in Compile := Seq(), - packageDoc in Compile <<= (packageDoc in documentation in Compile).identity, - packageSrc in Compile <<= (packageSrc in documentation in Compile).identity, - fullClasspath in Runtime <<= (exportedProducts in Compile).identity, - quickScalaInstance, - target <<= (baseDirectory, name) apply (_ / "target" / _) - ) - lazy val scalaLibrary = Project("scala-library", file(".")) settings(publishSettings:_*) settings(scalaLibArtifactSettings:_*) - - // -------------------------------------------------------------- - // Real Reflect Artifact - // -------------------------------------------------------------- - - lazy val packageScalaReflect = Seq(quickReflect).map(p => products in p in Compile).join.map(_.flatten).map(productTaskToMapping) - lazy val scalaReflectArtifactSettings : Seq[Setting[_]] = inConfig(Compile)(Defaults.packageTasks(packageBin, packageScalaReflect)) ++ Seq( - name := "scala-reflect", - crossPaths := false, - exportJars := true, - autoScalaLibrary := false, - unmanagedJars in Compile := Seq(), - fullClasspath in Runtime <<= (exportedProducts in Compile).identity, - quickScalaInstance, - target <<= (baseDirectory, name) apply (_ / "target" / _) - ) - lazy val scalaReflect = Project("scala-reflect", file(".")) settings(publishSettings:_*) settings(scalaReflectArtifactSettings:_*) dependsOn(scalaLibrary) - - - // -------------------------------------------------------------- - // Real Compiler Artifact - // -------------------------------------------------------------- - lazy val packageScalaBinTask = Seq(quickComp, asm).map(p => products in p in Compile).join.map(_.flatten).map(productTaskToMapping) - lazy val scalaBinArtifactSettings : Seq[Setting[_]] = inConfig(Compile)(Defaults.packageTasks(packageBin, packageScalaBinTask)) ++ Seq( - name := "scala-compiler", - crossPaths := false, - exportJars := true, - autoScalaLibrary := false, - unmanagedJars in Compile := Seq(), - fullClasspath in Runtime <<= (exportedProducts in Compile).identity, - quickScalaInstance, - target <<= (baseDirectory, name) apply (_ / "target" / _) - ) - lazy val scalaCompiler = Project("scala-compiler", file(".")) settings(publishSettings:_*) settings(scalaBinArtifactSettings:_*) dependsOn(scalaReflect) - lazy val fullQuickScalaReference = makeScalaReference("pack", scalaLibrary, scalaReflect, scalaCompiler) - - - // -------------------------------------------------------------- - // Generating Documentation. - // -------------------------------------------------------------- - - // TODO - Migrate this into the dist project. - // Scaladocs - lazy val documentationSettings: Seq[Setting[_]] = dependentProjectSettings ++ Seq( - // TODO - Make these work for realz. - defaultExcludes in unmanagedSources in Compile := ((".*" - ".") || HiddenFileFilter || - "reflect/Print.scala" || - "reflect/Symbol.scala" || - "reflect/Tree.scala" || - "reflect/Type.scala" || - "runtime/*$.scala" || - "runtime/ScalaRuntime.scala" || - "runtime/StringAdd.scala" || - "scala/swing/test/*"), - sourceFilter in Compile := ("*.scala"), - unmanagedSourceDirectories in Compile <<= baseDirectory apply { dir => - Seq(dir / "src" / "library" / "scala", dir / "src" / "actors", dir / "src" / "swing", dir / "src" / "continuations" / "library") - }, - compile := inc.Analysis.Empty, - // scaladocOptions in Compile <++= (baseDirectory) map (bd => - // Seq("-sourcepath", (bd / "src" / "library").getAbsolutePath, - // "-doc-no-compile", (bd / "src" / "library-aux").getAbsolutePath, - // "-doc-source-url", """https://lampsvn.epfl.ch/trac/scala/browser/scala/trunk/src/€{FILE_PATH}.scala#L1""", - // "-doc-root-content", (bd / "compiler/scala/tools/nsc/doc/html/resource/lib/rootdoc.txt").getAbsolutePath - // )), - classpathOptions in Compile := ClasspathOptions.manual - ) - lazy val documentation = ( - Project("documentation", file(".")) - settings (documentationSettings: _*) - dependsOn(quickLib, quickComp, actors, forkjoin, swing, continuationsLibrary) - ) -} diff --git a/project/Layers.scala b/project/Layers.scala deleted file mode 100644 index 6c939d0ff7..0000000000 --- a/project/Layers.scala +++ /dev/null @@ -1,116 +0,0 @@ -import sbt._ -import Keys._ -import com.jsuereth.git.GitKeys.gitRunner -import ScalaBuildKeys.lock - -/** This trait stores all the helper methods to generate layers in Scala's layered build. */ -trait Layers extends Build { - // TODO - Clean this up or use a self-type. - - /** Default SBT overrides needed for layered compilation. */ - def settingOverrides: Seq[Setting[_]] - /** Reference to the jline project */ - def jline: Project - /** Reference to forkjoin library */ - def forkjoin: Project - /** Reference to the ASM wrapped project. */ - def asm: Project - /** A setting that adds some external dependencies. */ - def externalDeps: Setting[_] - /** The root project. */ - def aaa_root: Project - - /** Creates a reference Scala version that can be used to build other projects. This takes in the raw - * library, compiler as well as a string representing the layer name (used for compiling the compile-interface). - */ - def makeScalaReference(layer: String, library: Project, reflect: Project, compiler: Project) = - scalaInstance <<= (appConfiguration in library, - version in library, - (exportedProducts in library in Compile), - (exportedProducts in reflect in Compile), - (exportedProducts in compiler in Compile), - (fullClasspath in jline in Runtime), - (exportedProducts in asm in Runtime)) map { - (app, version: String, lib: Classpath, reflect: Classpath, comp: Classpath, jline: Classpath, asm: Classpath) => - val launcher = app.provider.scalaProvider.launcher - (lib,comp) match { - case (Seq(libraryJar), Seq(compilerJar)) => - ScalaInstance( - version + "-" + layer + "-", - libraryJar.data, - compilerJar.data, - launcher, - ((jline.files ++ asm.files ++ reflect.files):_*)) - case _ => error("Cannot build a ScalaReference with more than one classpath element") - } - } - - /** Creates a "layer" of Scala compilation. That is, this will build the next version of Scala from a previous version. - * Returns the library project and compiler project from the next layer. - * Note: The library and compiler are not *complete* in the sense that they are missing things like "actors". - */ - def makeLayer(layer: String, referenceScala: Setting[Task[ScalaInstance]], autoLock: Boolean = false) : (Project, Project, Project) = { - val autoLockSettings: Seq[Setting[_]] = - if(autoLock) Seq(compile in Compile <<= (compile in Compile, lock) apply { (c, l) => - c flatMapR { cResult => - val result = Result.tryValue(cResult) - l mapR { tx => result } - } - }) - else Seq.empty - - - val library = Project(layer + "-library", file(".")) settings(settingOverrides: _*) settings(autoLockSettings:_*) settings( - version := layer, - // TODO - use depends on. - unmanagedClasspath in Compile <<= (exportedProducts in forkjoin in Compile).identity, - managedClasspath in Compile := Seq(), - scalaSource in Compile <<= (baseDirectory) apply (_ / "src" / "library"), - resourceDirectory in Compile <<= baseDirectory apply (_ / "src" / "library"), - defaultExcludes in unmanagedResources := ("*.scala" | "*.java" | "*.disabled"), - // TODO - Allow other scalac option settings. - scalacOptions in Compile <++= (scalaSource in Compile) map (src => Seq("-sourcepath", src.getAbsolutePath)), - resourceGenerators in Compile <+= (resourceManaged, Versions.scalaVersions, skip in Compile, streams) map Versions.generateVersionPropertiesFile("library.properties"), - referenceScala - ) - - // Define the reflection - val reflect = Project(layer + "-reflect", file(".")) settings(settingOverrides:_*) settings(autoLockSettings:_*) settings( - version := layer, - scalaSource in Compile <<= (baseDirectory) apply (_ / "src" / "reflect"), - resourceDirectory in Compile <<= baseDirectory apply (_ / "src" / "reflect"), - defaultExcludes := ("tests"), - defaultExcludes in unmanagedResources := "*.scala", - resourceGenerators in Compile <+= (resourceManaged, Versions.scalaVersions, skip in Compile, streams) map Versions.generateVersionPropertiesFile("reflect.properties"), - // TODO - Use depends on *and* SBT's magic dependency mechanisms... - unmanagedClasspath in Compile <<= Seq(forkjoin, library).map(exportedProducts in Compile in _).join.map(_.flatten), - externalDeps, - referenceScala - ) - - // Define the compiler - val compiler = Project(layer + "-compiler", file(".")) settings(settingOverrides:_*) settings(autoLockSettings:_*) settings( - version := layer, - scalaSource in Compile <<= (baseDirectory) apply (_ / "src" / "compiler"), - resourceDirectory in Compile <<= baseDirectory apply (_ / "src" / "compiler"), - defaultExcludes := ("tests"), - defaultExcludes in unmanagedResources := "*.scala", - resourceGenerators in Compile <+= (resourceManaged, Versions.scalaVersions, skip in Compile, streams) map Versions.generateVersionPropertiesFile("compiler.properties"), - // Note, we might be able to use the default task, but for some reason ant was filtering files out. Not sure what's up, but we'll - // stick with that for now. - unmanagedResources in Compile <<= (baseDirectory) map { - (bd) => - val dirs = Seq(bd / "src" / "compiler") - dirs.descendentsExcept( ("*.xml" | "*.html" | "*.gif" | "*.png" | "*.js" | "*.css" | "*.tmpl" | "*.swf" | "*.properties" | "*.txt"),"*.scala").get - }, - // TODO - Use depends on *and* SBT's magic dependency mechanisms... - unmanagedClasspath in Compile <<= Seq(forkjoin, library, reflect, jline, asm).map(exportedProducts in Compile in _).join.map(_.flatten), - externalDeps, - referenceScala - ) - - // Return the generated projects. - (library, reflect, compiler) - } - -} diff --git a/project/Packaging.scala b/project/Packaging.scala deleted file mode 100644 index b0060283ac..0000000000 --- a/project/Packaging.scala +++ /dev/null @@ -1,129 +0,0 @@ -import sbt._ -import Keys._ -import ScalaBuildKeys._ - -/** All the settings related to *packaging* the built scala software. */ -trait Packaging { self: ScalaBuild.type => - - // -------------------------------------------------------------- - // Packaging a distro - // -------------------------------------------------------------- - lazy val scalaDistSettings: Seq[Setting[_]] = Seq( - crossPaths := false, - target <<= (baseDirectory, name) apply (_ / "target" / _), - scalaSource in Compile <<= (baseDirectory, name) apply (_ / "src" / _), - autoScalaLibrary := false, - unmanagedJars in Compile := Seq(), - genBinRunner <<= (fullClasspath in quickComp in Runtime) map (new ScalaToolRunner(_)), - binDir <<= target(_/"bin"), - genBin <<= genBinTask(genBinRunner, binDir, fullClasspath in Runtime, false), - binDir in genBinQuick <<= baseDirectory apply (_ / "target" / "bin"), - // Configure the classpath this way to avoid having .jar files and previous layers on the classpath. - fullClasspath in Runtime in genBinQuick <<= Seq(quickComp,quickLib,scalap,actors,swing,jline,forkjoin).map(classDirectory in Compile in _).join.map(Attributed.blankSeq), - fullClasspath in Runtime in genBinQuick <++= (fullClasspath in Compile in jline), - genBinQuick <<= genBinTask(genBinRunner, binDir in genBinQuick, fullClasspath in Runtime in genBinQuick, true), - runManmakerMan <<= runManmakerTask(fullClasspath in Runtime in manmaker, runner in manmaker, "scala.tools.docutil.EmitManPage", "man1", ".1"), - runManmakerHtml <<= runManmakerTask(fullClasspath in Runtime in manmaker, runner in manmaker, "scala.tools.docutil.EmitHtml", "doc", ".html"), - // TODO - We could *really* clean this up in many ways. Let's look into making a Seq of "direct jars" (scalaLibrary, scalaCompiler, jline, scalap) - // a seq of "plugin jars" (continuationsPlugin) and "binaries" (genBin) and "documentation" mappings (genBin) that this can aggregate. - // really need to figure out a better way to pull jline + jansi. - makeDistMappings <<= (genBin, - runManmakerMan, - runManmakerHtml, - packageBin in scalaLibrary in Compile, - packageBin in scalaCompiler in Compile, - packageBin in jline in Compile, - packageBin in continuationsPlugin in Compile, - managedClasspath in jline in Compile, - packageBin in scalap in Compile) map { - (binaries, man, html, lib, comp, jline, continuations, jlineDeps, scalap) => - val jlineDepMap: Seq[(File, String)] = jlineDeps.map(_.data).flatMap(_ x Path.flat) map { case(a,b) => a -> ("lib/"+b) } - binaries ++ man ++ html ++ jlineDepMap ++ Seq( - lib -> "lib/scala-library.jar", - comp -> "lib/scala-compiler.jar", - jline -> "lib/jline.jar", - continuations -> "misc/scala-devel/plugins/continuations.jar", - scalap -> "lib/scalap.jar" - ) - }, - // Add in some more dependencies - makeDistMappings <+= (packageBin in swing in Compile) map (s => s -> "lib/scala-swing.jar"), - makeDistMappings <+= (packageBin in scalaReflect in Compile) map (s => s -> "lib/scala-reflect.jar"), - makeDist <<= (makeDistMappings, baseDirectory, streams) map { (maps, dir, s) => - s.log.debug("Map = " + maps.mkString("\n")) - val file = dir / "target" / "scala-dist.zip" - IO.zip(maps, file) - s.log.info("Created " + file.getAbsolutePath) - file - }, - makeExplodedDist <<= (makeDistMappings, target, streams) map { (maps, dir, s) => - def sameFile(f: File, f2: File) = f.getCanonicalPath == f2.getCanonicalPath - IO.createDirectory(dir) - IO.copy(for { - (file, name) <- maps - val file2 = dir / name - if !sameFile(file,file2) - } yield (file, file2)) - // Hack to make binaries be executable. TODO - Fix for JDK 5 and below... - maps map (_._2) filter (_ startsWith "bin/") foreach (dir / _ setExecutable true) - dir - } - ) - lazy val scaladist = ( - Project("dist", file(".")) - settings (scalaDistSettings: _*) - ) - - -// Helpers to make a distribution - - /** Generates runner scripts for distribution. */ - def genBinTask( - runner: ScopedTask[ScalaToolRunner], - outputDir: ScopedSetting[File], - classpath: ScopedTask[Classpath], - useClasspath: Boolean - ): Project.Initialize[sbt.Task[Seq[(File,String)]]] = { - (runner, outputDir, classpath, streams) map { (runner, outDir, cp, s) => - IO.createDirectory(outDir) - val classToFilename = Seq( - "scala.tools.nsc.MainGenericRunner" -> "scala", - "scala.tools.nsc.Main" -> "scalac", - "scala.tools.nsc.ScalaDoc" -> "scaladoc", - "scala.tools.nsc.CompileClient" -> "fsc", - "scala.tools.scalap.Main" -> "scalap" - ) - if (useClasspath) { - val classpath = Build.data(cp).map(_.getCanonicalPath).distinct.mkString(",") - s.log.debug("Setting classpath = " + classpath) - runner setClasspath classpath - } - def genBinFiles(cls: String, dest: File) = { - runner.setClass(cls) - runner.setFile(dest) - runner.execute() - // TODO - Mark generated files as executable (755 or a+x) that is *not* JDK6 specific... - dest.setExecutable(true) - } - def makeBinMappings(cls: String, binName: String): Seq[(File,String)] = { - val file = outDir / binName - val winBinName = binName + ".bat" - genBinFiles(cls, file) - Seq( file -> ("bin/"+binName), outDir / winBinName -> ("bin/"+winBinName) ) - } - classToFilename.flatMap((makeBinMappings _).tupled) - } - } - /** Creates man pages for distribution. */ - def runManmakerTask(classpath: ScopedTask[Classpath], scalaRun: ScopedTask[ScalaRun], mainClass: String, dir: String, ext: String): Project.Initialize[Task[Seq[(File,String)]]] = - (classpath, scalaRun, streams, target) map { (cp, runner, s, target) => - val binaries = Seq("fsc", "scala", "scalac", "scaladoc", "scalap") - binaries map { bin => - val file = target / "man" / dir / (bin + ext) - val classname = "scala.man1." + bin - IO.createDirectory(file.getParentFile) - toError(runner.run(mainClass, Build.data(cp), Seq(classname, file.getAbsolutePath), s.log)) - file -> ("man/" + dir + "/" + bin + ext) - } - } -} diff --git a/project/Partest.scala b/project/Partest.scala deleted file mode 100644 index 2ea41ba80b..0000000000 --- a/project/Partest.scala +++ /dev/null @@ -1,140 +0,0 @@ -import sbt._ - -import Build._ -import Keys._ -import Project.Initialize -import complete._ -import scala.collection.{ mutable, immutable } - -/** This object */ -object partest { - - /** The key for the run-partest task that exists in Scala's test suite. */ - lazy val runPartest = TaskKey[Unit]("run-partest", "Runs the partest test suite against the quick.") - lazy val runPartestSingle = InputKey[Unit]("run-partest-single", "Runs a single partest test against quick.") - lazy val runPartestFailed = TaskKey[Unit]("run-partest-failed", "Runs failed partest tests.") - lazy val runPartestGrep = InputKey[Unit]("run-partest-grep", "Runs a single partest test against quick.") - lazy val partestRunner = TaskKey[PartestRunner]("partest-runner", "Creates a runner that can run partest suites") - lazy val partestTests = TaskKey[Map[String, Seq[File]]]("partest-tests", "Creates a map of test-type to a sequence of the test files/directoryies to test.") - lazy val partestDirs = SettingKey[Map[String,File]]("partest-dirs", "The map of partest test type to directory associated with that test type") - - lazy val partestTaskSettings: Seq[Setting[_]] = Seq( - javaOptions in partestRunner := Seq("-Xmx512M -Xms256M"), - partestDirs <<= baseDirectory apply { bd => - partestTestTypes map (kind => kind -> (bd / "test" / "files" / kind)) toMap - }, - partestRunner <<= partestRunnerTask(fullClasspath in Runtime, javaOptions in partestRunner), - partestTests <<= partestTestsTask(partestDirs), - runPartest <<= runPartestTask(partestRunner, partestTests, scalacOptions in Test), - runPartestSingle <<= runSingleTestTask(partestRunner, partestDirs, scalacOptions in Test), - runPartestFailed <<= runPartestTask(partestRunner, partestTests, scalacOptions in Test, Seq("--failed")) - ) - - // What's fun here is that we want "*.scala" files *and* directories in the base directory... - def partestResources(base: File, testType: String): PathFinder = testType match { - case "res" => base ** "*.res" - // TODO - Only allow directories that have "*.scala" children... - case _ => base * "*" filter { f => !f.getName.endsWith(".obj") && (f.isDirectory || f.getName.endsWith(".scala")) } - } - lazy val partestTestTypes = Seq("run", "jvm", "pos", "neg", "res", "shootout", "scalap", "specialized", "presentation", "scalacheck") - - // TODO - Figure out how to specify only a subset of resources... - def partestTestsTask(testDirs: ScopedSetting[Map[String,File]]): Project.Initialize[Task[Map[String, Seq[File]]]] = - testDirs map (m => m map { case (kind, dir) => kind -> partestResources(dir, kind).get }) - - // TODO - Split partest task into Configurations and build a Task for each Configuration. - // *then* mix all of them together for run-testsuite or something clever like this. - def runPartestTask(runner: ScopedTask[PartestRunner], testRuns: ScopedTask[Map[String,Seq[File]]], scalacOptions: ScopedTask[Seq[String]], extraArgs: Seq[String] = Seq()): Initialize[Task[Unit]] = { - (runner, testRuns, scalacOptions, streams) map { - (runner, runs, scalaOpts, s) => runPartestImpl(runner, runs, scalaOpts, s, extraArgs) - } - } - private def runPartestImpl(runner: PartestRunner, runs: Map[String, Seq[File]], scalacOptions: Seq[String], s: TaskStreams, extras: Seq[String] = Seq()): Unit = { - val testArgs = runs.toSeq collect { case (kind, files) if files.nonEmpty => Seq("-" + kind, files mkString ",") } flatten - val extraArgs = scalacOptions flatMap (opt => Seq("-scalacoption", opt)) - - import collection.JavaConverters._ - val results = runner run Array(testArgs ++ extraArgs ++ extras: _*) asScala - // TODO - save results - val failures = results collect { - case (path, "FAIL") => path + " [FAILED]" - case (path, "TIMEOUT") => path + " [TIMEOUT]" - } - - if (failures.isEmpty) - s.log.info(""+results.size+" tests passed.") - else { - failures foreach (s.log error _) - error("Test Failures! ("+failures.size+" of "+results.size+")") - } - } - - def convertTestsForAutoComplete(tests: Map[String, Seq[File]]): (Set[String], Set[String]) = - (tests.keys.toSet, tests.values flatMap (_ map cleanFileName) toSet) - - /** Takes a test file, as sent ot Partest, and cleans it up for auto-complete */ - def cleanFileName(file: File): String = { - // TODO - Something intelligent here - val TestPattern = ".*/test/(.*)".r - file.getCanonicalPath match { - case TestPattern(n) => n - case _ => file.getName - } - } - - // TODO - Allow a filter for the second part of this... - def runSingleTestParser(testDirs: Map[String, File]): State => Parser[(String, String)] = { - import DefaultParsers._ - state => { - Space ~> token(NotSpace examples testDirs.keys.toSet) flatMap { kind => - val files: Set[String] = testDirs get kind match { - case Some(dir) => - partestResources(dir, kind).get flatMap (_ relativeTo dir) map (_ getName) toSet - case _ => - Set() - } - Space ~> token(NotSpace examples files) map (kind -> _) - } - } - } - - def runSingleTestTask(runner: ScopedTask[PartestRunner], testDirs: ScopedSetting[Map[String, File]], scalacOptions: ScopedTask[Seq[String]]) : Initialize[InputTask[Unit]] = { - import sbinary.DefaultProtocol._ - - InputTask(testDirs apply runSingleTestParser) { result => - (runner, result, testDirs, scalacOptions, streams) map { - case (r, (kind, filter), dirs, o, s) => - // TODO - Use partest resources somehow to filter the filter correctly.... - val files: Seq[File] = - if (filter == "*") partestResources(dirs(kind), kind).get - else (dirs(kind) * filter).get - - runPartestImpl(r, Map(kind -> files), o, s) - } - } - } - - def partestRunnerTask(classpath: ScopedTask[Classpath], javacOptions: TaskKey[Seq[String]]): Project.Initialize[Task[PartestRunner]] = - (classpath, javacOptions) map ((cp, opts) => new PartestRunner(Build.data(cp), opts mkString " ")) -} - -class PartestRunner(classpath: Seq[File], javaOpts: String) { - // Classloader that does *not* have this as parent, for differing Scala version. - lazy val classLoader = new java.net.URLClassLoader(classpath.map(_.toURI.toURL).toArray, null) - lazy val (mainClass, mainMethod) = try { - val c = classLoader.loadClass("scala.tools.partest.nest.SBTRunner") - val m = c.getMethod("mainReflect", classOf[Array[String]]) - (c,m) - } - lazy val classPathArgs = Seq("-cp", classpath.map(_.getAbsoluteFile).mkString(java.io.File.pathSeparator)) - def run(args: Array[String]): java.util.Map[String,String] = try { - // TODO - undo this settings after running. Also globals are bad. - System.setProperty("partest.java_opts", javaOpts) - val allArgs = (classPathArgs ++ args).toArray - mainMethod.invoke(null, allArgs).asInstanceOf[java.util.Map[String,String]] - } catch { - case e => - //error("Could not run Partest: " + e) - throw e - } -} diff --git a/project/Release.scala b/project/Release.scala deleted file mode 100644 index feab8bdc8c..0000000000 --- a/project/Release.scala +++ /dev/null @@ -1,30 +0,0 @@ -import sbt._ -import Keys._ - -object Release { - - // TODO - Just make the STARR artifacts and dump the sha1 files. - - val starrLibs = Seq("scala-library.jar", "scala-reflect.jar", "scala-compiler.jar", "jline.jar") - - val pushStarr = Command.command("new-starr") { (state: State) => - /*val extracted = Project.extract(state) - import extracted._ - // First run tests - val (s1, result) = runTask(test in Test, state) - // If successful, package artifacts - val (s2, distDir) = runTask(makeExplodedDist, s1) - // Then copy new libs in place - val bd = extracted get baseDirectory - for { - jarName <- starrLibs - jar = distDir / "lib" / jarName - if jar.exists - } IO.copyFile(jar, bd / "lib" / jarName) - // Invalidate SHA1 files. - ShaResolve.removeInvalidShaFiles(bd) - // Now run tests *again*? - s2*/ - state - } -} diff --git a/project/RemoteDependencies.scala b/project/RemoteDependencies.scala deleted file mode 100644 index 705b9dc402..0000000000 --- a/project/RemoteDependencies.scala +++ /dev/null @@ -1,53 +0,0 @@ -import sbt._ -import Keys._ -import ScalaBuildKeys._ - - -object RemoteDependencies { - def buildSettings(externalProjects: Set[URI], localScala: Setting[_]): Seq[Setting[_]] = Seq( - commands += Command.command("fix-uri-projects") { (state: State) => - if(state.get(buildFixed) getOrElse false) state - else { - // TODO -fix up scalacheck's dependencies! - val extracted = Project.extract(state) - import extracted._ - val scalaVersionString = extracted get version - - def fix(s: Setting[_]): Setting[_] = s match { - case ScopedExternalSetting(p, scalaInstance.key, setting) if externalProjects(p) => localScala mapKey Project.mapScope(_ => s.key.scope) - // TODO - Fix Actors dependency... - //case ScopedExternalSetting(p, libraryDependencies.key, setting) if externalProjects(p) => fixProjectDeps(s) - case s => s - } - val transformed = session.mergeSettings map ( s => fix(s) ) - val scopes = transformed collect { case ScopedExternalSetting(p, _, s) if externalProjects(p) => s.key.scope } toSet - // Create some fixers so we don't download scala or rely on it. - // Also add dependencies that disappear in 2.10 for now... - val fixers = for { scope <- scopes - setting <- Seq(autoScalaLibrary := false, - crossPaths := false, - scalaVersion := scalaVersionString) - } yield setting mapKey Project.mapScope(_ => scope) - val newStructure = Load.reapply(transformed ++ fixers, structure) - Project.setProject(session, newStructure, state).put(buildFixed, true) - } - }, - onLoad in Global <<= (onLoad in Global) apply (_ andThen { (state: State) => - "fix-uri-projects" :: state - }) - ) -} - - - -/** Matcher to make updated remote project references easier. */ -object ScopedExternalSetting { - def unapply[T](s: Setting[_]): Option[(URI, AttributeKey[_], Setting[_])] = - s.key.scope.project match { - case Select(p @ ProjectRef(uri, _)) => Some((uri, s.key.key, s)) - case _ => None - } -} - - - diff --git a/project/Sametest.scala b/project/Sametest.scala deleted file mode 100644 index 6f12eb24b3..0000000000 --- a/project/Sametest.scala +++ /dev/null @@ -1,63 +0,0 @@ -import sbt._ - -import Build._ -import Keys._ - -// This code is adapted from scala.tools.ant.Same by Gilles Dubochet. -object SameTest { - - def checkSameBinaryProjects(lhs: Project, rhs: Project): Project.Initialize[Task[Unit]] = - (classDirectory in Compile in lhs, classDirectory in Compile in rhs, - compile in Compile in lhs, compile in Compile in rhs, streams) map { (lhs,rhs, _, _, s) => - // Now we generate a complete set of relative files and then - def relativeClasses(dir: File) = (dir ** "*.class").get.flatMap(IO.relativize(dir,_).toList) - // This code adapted from SameTask in the compiler. - def hasDifferentFiles(filePairs: Seq[(File,File)]): Boolean = { - filePairs exists { case (a,b) => - if (!a.canRead || !b.canRead) { - s.log.error("Either ["+a+"] or ["+b+"] is missing.") - true - } else { - s.log.debug("Checking for binary differences in ["+a+"] against ["+b+"].") - val diff = !checkSingleFilePair(a,b) - if(diff) s.log.error("["+a+"] differs from ["+b+"]") - diff - } - } - } - val allClassMappings = (relativeClasses(lhs) ++ relativeClasses(rhs)).distinct - val comparisons = allClassMappings.map(f => new File(lhs, f) -> new File(rhs, f)) - val result = hasDifferentFiles(comparisons) - if (result) error("Binary artifacts differ.") - } - - val bufferSize = 1024 - - // Tests whether two files are binary equivalents of each other. - def checkSingleFilePair(originFile: File, destFile: File): Boolean = { - Using.fileInputStream(originFile) { originStream => - Using.fileInputStream(destFile) { destStream => - val originBuffer = new Array[Byte](bufferSize) - val destBuffer = new Array[Byte](bufferSize) - var equalNow = true - var originRemaining = originStream.read(originBuffer) - var destRemaining = destStream.read(destBuffer) - while (originRemaining > 0 && equalNow) { - if (originRemaining == destRemaining) { - for (idx <- 0 until originRemaining) { - equalNow = equalNow && (originBuffer(idx) == destBuffer(idx)) - } - } else { - equalNow = false - } - originRemaining = originStream.read(originBuffer) - destRemaining = destStream.read(destBuffer) - } - if (destRemaining > 0) equalNow = false - equalNow - } - } - } - - -} diff --git a/project/ScalaBuildKeys.scala b/project/ScalaBuildKeys.scala deleted file mode 100644 index 9e495de19f..0000000000 --- a/project/ScalaBuildKeys.scala +++ /dev/null @@ -1,23 +0,0 @@ -import sbt._ -import Keys._ - -object ScalaBuildKeys { - val lockerLock = TaskKey[Unit]("locker-lock", "Locks the locker layer of the compiler build such that it won't rebuild on changed source files.") - val lockerUnlock = TaskKey[Unit]("locker-unlock", "Unlocks the locker layer of the compiler so that it will be recompiled on changed source files.") - val lockFile = SettingKey[File]("lock-file", "Location of the lock file compiling this project.") - val lock = TaskKey[Unit]("lock", "Locks this project so it won't be recompiled.") - val unlock = TaskKey[Unit]("unlock", "Unlocks this project so it will be recompiled.") - val makeDist = TaskKey[File]("make-dist", "Creates a mini-distribution (scala home directory) for this build in a zip file.") - val makeExplodedDist = TaskKey[File]("make-exploded-dist", "Creates a mini-distribution (scala home directory) for this build in a directory.") - val makeDistMappings = TaskKey[Seq[(File, String)]]("make-dist-mappings", "Creates distribution mappings for creating zips,jars,directorys,etc.") - val buildFixed = AttributeKey[Boolean]("build-uri-fixed") - val genBinRunner = TaskKey[ScalaToolRunner]("gen-bin-runner", "Creates a utility to generate script files for Scala.") - val genBin = TaskKey[Seq[(File,String)]]("gen-bin", "Creates script files for Scala distribution.") - val binDir = SettingKey[File]("binaries-directory", "Directory where binary scripts will be located.") - val genBinQuick = TaskKey[Seq[(File,String)]]("gen-quick-bin", "Creates script files for testing against current Scala build classfiles (not local dist).") - val runManmakerMan = TaskKey[Seq[(File,String)]]("make-man", "Runs the man maker project to generate man pages") - val runManmakerHtml = TaskKey[Seq[(File,String)]]("make-html", "Runs the man maker project to generate html pages") - val checkSame = TaskKey[Unit]("check-same-binaries", "checks whether or not the class files generated by scala are the same.") - val checkSameLibrary = TaskKey[Unit]("check-same-lib-binaries", "checks whether or not the librayr class files generated by scala are the same.") - val checkSameCompiler = TaskKey[Unit]("check-same-comp-binaries", "checks whether or not the compiler class files generated by scala are the same.") -} diff --git a/project/ScalaToolRunner.scala b/project/ScalaToolRunner.scala deleted file mode 100644 index d7338a54b3..0000000000 --- a/project/ScalaToolRunner.scala +++ /dev/null @@ -1,21 +0,0 @@ -import sbt._ -import Keys._ - -/** Reflection helper that runs ScalaTool. - * TODO - When SBT is on 2.10.x try to use Dynamic + Reflection. COULD BE FUN. - */ -class ScalaToolRunner(classpath: Classpath) { - // TODO - Don't use the ant task directly... - lazy val classLoader = new java.net.URLClassLoader(classpath.map(_.data.toURI.toURL).toArray, null) - lazy val mainClass = classLoader.loadClass("scala.tools.ant.ScalaTool") - lazy val executeMethod = mainClass.getMethod("execute") - lazy val setFileMethod = mainClass.getMethod("setFile", classOf[java.io.File]) - lazy val setClassMethod = mainClass.getMethod("setClass", classOf[String]) - lazy val setClasspathMethod = mainClass.getMethod("setClassPath", classOf[String]) - lazy val instance = mainClass.newInstance() - - def setClass(cls: String): Unit = setClassMethod.invoke(instance, cls) - def setFile(file: File): Unit = setFileMethod.invoke(instance, file) - def setClasspath(cp: String): Unit = setClasspathMethod.invoke(instance, cp) - def execute(): Unit = executeMethod.invoke(instance) -} diff --git a/project/ShaResolve.scala b/project/ShaResolve.scala deleted file mode 100644 index e5b25a29cf..0000000000 --- a/project/ShaResolve.scala +++ /dev/null @@ -1,148 +0,0 @@ -import sbt._ - -import Build._ -import Keys._ -import Project.Initialize -import scala.collection.{ mutable, immutable } -import scala.collection.parallel.CompositeThrowable -import java.security.MessageDigest - -case class Credentials(user: String, pw: String) - -/** Helpers to resolve SHA artifacts from typesafe repo. */ -object ShaResolve { - import dispatch.{Http,url} - val remote_urlbase="http://typesafe.artifactoryonline.com/typesafe/scala-sha-bootstrap/org/scala-lang/bootstrap" - - val pullBinaryLibs = TaskKey[Unit]("pull-binary-libs", "Pulls binary libs by the SHA key.") - val pushBinaryLibs = TaskKey[Unit]("push-binary-libs", "Pushes binary libs whose SHA has changed.") - val binaryLibCache = SettingKey[File]("binary-lib-cache", "Location of the cache of binary libs for this scala build.") - - def settings: Seq[Setting[_]] = Seq( - binaryLibCache in ThisBuild := file(System.getProperty("user.home")) / ".sbt" / "cache" / "scala", - pullBinaryLibs in ThisBuild <<= (baseDirectory, binaryLibCache, streams) map resolveLibs, - pushBinaryLibs in ThisBuild <<= (baseDirectory, streams) map getCredentialsAndPushFiles - ) - - def resolveLibs(dir: File, cacheDir: File, s: TaskStreams): Unit = loggingParallelExceptions(s) { - val files = (dir / "test" / "files" ** "*.desired.sha1") +++ (dir / "lib" ** "*.desired.sha1") - for { - (file, name) <- (files x relativeTo(dir)).par - uri = name.dropRight(13).replace('\\', '/') - jar = dir / uri - if !jar.exists || !isValidSha(file) - sha = getShaFromShafile(file) - } pullFile(jar, sha + "/" + uri, cacheDir, sha, s) - } - - /** This method removes all SHA1 files that don't match their corresponding JAR. */ - def removeInvalidShaFiles(dir: File): Unit = { - val files = (dir / "test" / "files" ** "*.desired.sha1") +++ (dir / "lib" ** "*.desired.sha1") - for { - (file, name) <- (files x relativeTo(dir)).par - uri = name.dropRight(13).replace('\\', '/') - jar = dir / uri - if !jar.exists || !isValidSha(file) - } IO.delete(jar) - } - def getCredentials: Credentials = System.out.synchronized { - val user = (SimpleReader.readLine("Please enter your STARR username> ") getOrElse error("No username provided.")) - val password = (SimpleReader.readLine("Please enter your STARR password> ", Some('*')) getOrElse error("No password provided.")) - Credentials(user, password) - } - - def getCredentialsAndPushFiles(dir: File, s: TaskStreams): Unit = - pushFiles(dir, getCredentials, s) - - def pushFiles(dir: File, cred: Credentials, s: TaskStreams): Unit = loggingParallelExceptions(s) { - val files = (dir / "test" / "files" ** "*.jar") +++ (dir / "lib" ** "*.jar") - for { - (jar, name) <- (files x relativeTo(dir)).par - shafile = dir / (name + ".desired.sha1") - if !shafile.exists || !isValidSha(shafile) - } pushFile(jar, name, cred, s) - } - - @inline final def loggingParallelExceptions[U](s: TaskStreams)(f: => U): U = try f catch { - case t: CompositeThrowable => - s.log.error("Error during parallel execution, GET READY FOR STACK TRACES!!") - t.throwables foreach (t2 => s.log.trace(t2)) - throw t - } - - // TODO - Finish this publishing aspect. - - def getShaFromShafile(file: File): String = parseShaFile(file)._2 - - // This should calculate the SHA sum of a file the same as the linux process. - def calculateSha(file: File): String = { - val digest = MessageDigest.getInstance("SHA1") - val in = new java.io.FileInputStream(file); - val buffer = new Array[Byte](8192) - try { - def read(): Unit = in.read(buffer) match { - case x if x <= 0 => () - case size => digest.update(buffer, 0, size); read() - } - read() - } finally in.close() - val sha = convertToHex(digest.digest()) - sha - } - - def convertToHex(data: Array[Byte]): String = { - def byteToHex(b: Int) = - if ((0 <= b) && (b <= 9)) ('0' + b).toChar - else ('a' + (b-10)).toChar - val buf = new StringBuffer - for (i <- 0 until data.length) { - buf append byteToHex((data(i) >>> 4) & 0x0F) - buf append byteToHex(data(i) & 0x0F) - } - buf.toString - } - // Parses a sha file into a file and a sha. - def parseShaFile(file: File): (File, String) = - IO.read(file).split("\\s") match { - case Array(sha, filename) if filename.startsWith("?") => (new File(file.getParentFile, filename.drop(1)), sha) - case Array(sha, filename) if filename.startsWith("*") => (new File(file.getParentFile, filename.drop(1)), sha) - case Array(sha, filename) => (new File(file.getParentFile, filename), sha) - case _ => error(file.getAbsolutePath + " is an invalid sha file") - } - - - def isValidSha(file: File): Boolean = - try { - val (jar, sha) = parseShaFile(file) - jar.exists && calculateSha(jar) == sha - } catch { - case t: Exception => false - } - - - def pullFile(file: File, uri: String, cacheDir: File, sha: String, s: TaskStreams): Unit = { - val cachedFile = cacheDir / uri - if (!cachedFile.exists || calculateSha(cachedFile) != sha) { - // Ensure the directory for the cache exists. - cachedFile.getParentFile.mkdirs() - val url = remote_urlbase + "/" + uri - val fous = new java.io.FileOutputStream(cachedFile) - s.log.info("Pulling [" + cachedFile + "] to cache") - try Http(dispatch.url(url) >>> fous) finally fous.close() - } - s.log.info("Pulling [" + file + "] from local cache") - IO.copyFile(cachedFile, file) - } - - // Pushes a file and writes the new .desired.sha1 for git. - def pushFile(file: File, uri: String, cred: Credentials, s: TaskStreams): Unit = { - val sha = calculateSha(file) - val url = remote_urlbase + "/" + sha + "/" + uri - val sender = dispatch.url(url).PUT.as(cred.user,cred.pw) <<< (file, "application/java-archive") - // TODO - output to logger. - Http(sender >>> System.out) - val shafile = file.getParentFile / (file.getName + ".desired.sha1") - IO.touch(shafile) - IO.write(shafile, sha + " ?" + file.getName) - } -} diff --git a/project/Testing.scala b/project/Testing.scala deleted file mode 100644 index 5b4135a31a..0000000000 --- a/project/Testing.scala +++ /dev/null @@ -1,41 +0,0 @@ -import sbt._ -import Keys._ -import partest._ -import SameTest._ -import ScalaBuildKeys._ - -/** All settings/projects relating to testing. */ -trait Testing { self: ScalaBuild.type => - - lazy val testsuiteSettings: Seq[Setting[_]] = compilerDependentProjectSettings ++ partestTaskSettings ++ VerifyClassLoad.settings ++ Seq( - unmanagedBase <<= baseDirectory / "test/files/lib", - fullClasspath in VerifyClassLoad.checkClassLoad <<= (fullClasspath in scalaLibrary in Runtime).identity, - autoScalaLibrary := false, - checkSameLibrary <<= checkSameBinaryProjects(quickLib, strappLib), - checkSameCompiler <<= checkSameBinaryProjects(quickComp, strappComp), - checkSame <<= (checkSameLibrary, checkSameCompiler) map ((a,b) => ()), - autoScalaLibrary := false - ) - lazy val continuationsTestsuiteSettings: Seq[Setting[_]] = testsuiteSettings ++ Seq( - scalacOptions in Test <++= (exportedProducts in Compile in continuationsPlugin) map { - case Seq(cpDir) => Seq("-Xplugin-require:continuations", "-P:continuations:enable", "-Xplugin:"+cpDir.data.getAbsolutePath) - }, - partestDirs <<= baseDirectory apply { bd => - def mkFile(name: String) = bd / "test" / "files" / name - def mkTestType(name: String) = name.drop("continuations-".length).toString - Seq("continuations-neg", "continuations-run") map (t => mkTestType(t) -> mkFile(t)) toMap - } - ) - val testsuite = ( - Project("testsuite", file(".")) - settings (testsuiteSettings:_*) - dependsOn (scalaLibrary, scalaCompiler, partest, scalacheck) - ) - val continuationsTestsuite = ( - Project("continuations-testsuite", file(".")) - settings (continuationsTestsuiteSettings:_*) - dependsOn (partest, scalaLibrary, scalaCompiler) - ) - -} - diff --git a/project/VerifyClassLoad.scala b/project/VerifyClassLoad.scala deleted file mode 100644 index c8eebb1159..0000000000 --- a/project/VerifyClassLoad.scala +++ /dev/null @@ -1,46 +0,0 @@ -import sbt._ - -import Build._ -import Keys._ - -// This is helper code to validate that generated class files will succed in bytecode verification at class-load time. -object VerifyClassLoad { - lazy val checkClassLoad: TaskKey[Unit] = TaskKey("check-class-load", "checks whether or not the class files generated by scala are deemed acceptable by classloaders.") - lazy val checkClassRunner: TaskKey[ClassVerifyRunner] = TaskKey("check-class-runner", "A wrapper around reflective calls to the VerifyClass class.") - - - def settings: Seq[Setting[_]] = Seq( - checkClassRunner <<= (fullClasspath in Runtime) map (cp => new ClassVerifyRunner(data(cp))), - fullClasspath in checkClassLoad := Seq(), - checkClassLoad <<= (checkClassRunner, fullClasspath in checkClassLoad, streams) map { (runner, dirs, s) => - import collection.JavaConverters._ - val results = runner.run(data(dirs).map(_.getAbsolutePath).toArray).asScala - - s.log.info("Processed " + results.size + " classes.") - val errors = results.filter(_._2 != null) - for( (name, result) <- results; if result != null) { - s.log.error(name + " had error: " + result) - } - if(errors.size > 0) error("Classload validation errors encountered") - () - } - ) - - // TODO - Use - class ClassVerifyRunner(classpath: Seq[File]) { - // Classloader that does *not* have this as parent, for differing Scala version. - lazy val classLoader = new java.net.URLClassLoader(classpath.map(_.toURI.toURL).toArray, null) - lazy val (mainClass, mainMethod) = try { - val c = classLoader.loadClass("scala.tools.util.VerifyClass") - val m = c.getMethod("run", classOf[Array[String]]) - (c,m) - } - def run(args: Array[String]): java.util.Map[String,String] = try { - mainMethod.invoke(null, args).asInstanceOf[java.util.Map[String,String]] - } catch { - case e => - //error("Could not run Partest: " + e) - throw e - } - } -} diff --git a/project/Versions.scala b/project/Versions.scala deleted file mode 100644 index 57e274c15c..0000000000 --- a/project/Versions.scala +++ /dev/null @@ -1,142 +0,0 @@ -import sbt._ -import Keys._ -import java.util.Properties -import scala.util.control.Exception.catching -import java.lang.{NumberFormatException => NFE} -import java.io.FileInputStream -import com.jsuereth.git.GitRunner -import com.jsuereth.git.GitKeys.gitRunner - -case class VersionInfo(canonical: String, - maven: String, - osgi: String) - -/** this file is responsible for setting up Scala versioning schemes and updating all the necessary bits. */ -object Versions { - val buildNumberFile = SettingKey[File]("scala-build-number-file") - // TODO - Make this a setting? - val buildNumberProps = SettingKey[BaseBuildNumber]("scala-build-number-props") - val buildRelease = SettingKey[Boolean]("scala-build-release", "This is set to true if we're building a release.") - val mavenSuffix = SettingKey[String]("scala-maven-suffix", "This is set to whatever maven suffix is required.") - - val gitSha = TaskKey[String]("scala-git-sha", "The sha of the current git commit.") - val gitDate = TaskKey[String]("scala-git-date", "The date of the current git commit.") - - val mavenVersion = SettingKey[String]("scala-maven-version", "The maven version number.") - val osgiVersion = TaskKey[String]("scala-osgi-version", "The OSGi version number.") - val canonicalVersion = TaskKey[String]("scala-canonical-version", "The canonical version number.") - - val scalaVersions = TaskKey[VersionInfo]("scala-version-info", "The scala versions used for this build.") - - - - def settings: Seq[Setting[_]] = Seq( - buildNumberFile <<= baseDirectory apply (_ / "build.number"), - buildNumberProps <<= buildNumberFile apply loadBuildNumberProps, - buildRelease := Option(System.getProperty("build.release")) map (!_.isEmpty) getOrElse false, - mavenSuffix <<= buildRelease apply pickMavenSuffix, - mavenVersion <<= (buildNumberProps, mavenSuffix) apply makeMavenVersion, - gitSha <<= (gitRunner, baseDirectory, streams) map getGitSha, - gitDate <<= (gitRunner, baseDirectory, streams) map getGitDate, - osgiVersion <<= (buildNumberProps, gitDate, gitSha) map makeOsgiVersion, - canonicalVersion <<= (buildRelease, mavenVersion, buildNumberProps, gitDate, gitSha) map makeCanonicalVersion, - scalaVersions <<= (canonicalVersion, mavenVersion, osgiVersion) map VersionInfo.apply - ) - - - /** This generates a properties file, if it does not already exist, with the maximum lastmodified timestamp - * of any source file. */ - def generateVersionPropertiesFile(name: String)(dir: File, versions: VersionInfo, skip: Boolean, s: TaskStreams): Seq[File] = { - // TODO - We can probably clean this up by moving caching bits elsewhere perhaps.... - val target = dir / name - // TODO - Regenerate on triggers, like recompilation or something... - def hasSameVersion: Boolean = { - val props = new java.util.Properties - val in = new java.io.FileInputStream(target) - try props.load(in) finally in.close() - versions.canonical == (props getProperty "version.number") - } - if (!target.exists || !(skip || hasSameVersion)) { - makeVersionPropertiesFile(target, versions) - } - target :: Nil - } - - // This creates the *.properties file used to determine the current version of scala at runtime. TODO - move these somewhere utility like. - def makeVersionPropertiesFile(f: File, versions: VersionInfo): Unit = - IO.write(f, "version.number = "+versions.canonical+"\n"+ - "osgi.number = "+versions.osgi+"\n"+ - "maven.number = "+versions.maven+"\n"+ - "copyright.string = Copyright 2002-2013, LAMP/EPFL") - - def makeCanonicalVersion(isRelease: Boolean, mvnVersion: String, base: BaseBuildNumber, gitDate: String, gitSha: String): String = - if(isRelease) mvnVersion - else { - val suffix = if(base.bnum > 0) "-%d".format(base.bnum) else "" - "%s.%s.%s%s-%s-%s" format (base.major, base.minor, base.patch, suffix, gitDate, gitSha) - } - - def makeMavenVersion(base: BaseBuildNumber, suffix: String): String = { - val firstSuffix = if(base.bnum > 0) "-%d".format(base.bnum) else "" - "%d.%d.%d%s%s" format (base.major, base.minor, base.patch, firstSuffix, suffix) - } - - def makeOsgiVersion(base: BaseBuildNumber, gitDate: String, gitSha: String): String = { - val suffix = if(base.bnum > 0) "-%d".format(base.bnum) else "" - "%s.%s.%s.v%s%s-%s" format (base.major, base.minor, base.patch, gitDate, suffix, gitSha) - } - - /** Determines what the maven sufffix should be for this build. */ - def pickMavenSuffix(isRelease: Boolean): String = { - def default = if(isRelease) "" else "-SNAPSHOT" - Option(System.getProperty("maven.version.suffix")) getOrElse default - } - - /** Loads the build.number properties file into SBT. */ - def loadBuildNumberProps(file: File): BaseBuildNumber = { - val fin = new FileInputStream(file) - try { - val props = new Properties() - props.load(fin) - def getProp(name: String): Int = - (for { - v <- Option(props.getProperty(name)) - v2 <- catching(classOf[NFE]) opt v.toInt - } yield v2) getOrElse sys.error("Could not convert %s to integer!" format (name)) - - BaseBuildNumber( - major=getProp("version.major"), - minor=getProp("version.minor"), - patch=getProp("version.patch"), - bnum =getProp("version.bnum") - ) - } finally fin.close() - } - - - def getGitDate(git: GitRunner, baseDirectory: File, s: TaskStreams): String = { - val lines = getGitLines("log","-1","--format=\"%ci\"")(git,baseDirectory, s) - val line = if(lines.isEmpty) sys.error("Could not retreive git commit sha!") else lines.head - // Lines *always* start with " for some reason... - line drop 1 split "\\s+" match { - case Array(date, time, _*) => "%s-%s" format (date.replaceAll("\\-", ""), time.replaceAll(":","")) - case _ => sys.error("Could not parse git date: " + line) - } - } - - def getGitSha(git: GitRunner, baseDirectory: File, s: TaskStreams): String = { - val lines = getGitLines("log","-1","--format=\"%H\"", "HEAD")(git,baseDirectory, s) - val line = if(lines.isEmpty) sys.error("Could not retreive git commit sha!") else lines.head - val noquote = if(line startsWith "\"") line drop 1 else line - val nog = if(noquote startsWith "g") noquote drop 1 else noquote - nog take 10 - } - - def getGitLines(args: String*)(git: GitRunner, baseDirectory: File, s: TaskStreams): Seq[String] = - git(args: _*)(baseDirectory, s.log) split "[\r\n]+" -} - - -case class BaseBuildNumber(major: Int, minor: Int, patch: Int, bnum: Int) { - override def toString = "BaseBuildNumber(%d.%d.%d-%d)" format (major, minor, patch, bnum) -} diff --git a/project/plugins.sbt b/project/plugins.sbt deleted file mode 100644 index fdf37e31a6..0000000000 --- a/project/plugins.sbt +++ /dev/null @@ -1,9 +0,0 @@ -resolvers += Resolver.url("Typesafe nightlies", url("https://typesafe.artifactoryonline.com/typesafe/ivy-snapshots/"))(Resolver.ivyStylePatterns) - -resolvers += Resolver.url("scalasbt", new URL("http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases"))(Resolver.ivyStylePatterns) - -resolvers += "jgit-repo" at "http://download.eclipse.org/jgit/maven" - -libraryDependencies += "net.databinder" % "dispatch-http_2.9.1" % "0.8.6" - - diff --git a/project/project/Build.scala b/project/project/Build.scala deleted file mode 100644 index d3a08b62ba..0000000000 --- a/project/project/Build.scala +++ /dev/null @@ -1,7 +0,0 @@ -import sbt._ -object PluginDef extends Build { - override def projects = Seq(root) - lazy val root = Project("plugins", file(".")) dependsOn(proguard, git) - lazy val proguard = uri("git://github.com/jsuereth/xsbt-proguard-plugin.git#sbt-0.12") - lazy val git = uri("git://github.com/sbt/sbt-git.git#scala-build") -} diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala index 82a3144304..80b6ad3cc7 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala @@ -792,6 +792,7 @@ trait Scanners extends ScannersCommon { if (ch == '\\') { nextChar() if ('0' <= ch && ch <= '7') { + val start = charOffset - 2 val leadch: Char = ch var oct: Int = digit2int(ch, 8) nextChar() @@ -803,6 +804,12 @@ trait Scanners extends ScannersCommon { nextChar() } } + val alt = if (oct == LF) "\\n" else "\\u%04x" format oct + def msg(what: String) = s"Octal escape literals are $what, use $alt instead." + if (settings.future) + syntaxError(start, msg("unsupported")) + else + deprecationWarning(start, msg("deprecated")) putChar(oct.toChar) } else { ch match { diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 19a6e11986..ea2cbbe3d3 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -415,7 +415,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { val INNER_CLASSES_FLAGS = (asm.Opcodes.ACC_PUBLIC | asm.Opcodes.ACC_PRIVATE | asm.Opcodes.ACC_PROTECTED | - asm.Opcodes.ACC_STATIC | asm.Opcodes.ACC_INTERFACE | asm.Opcodes.ACC_ABSTRACT) + asm.Opcodes.ACC_STATIC | asm.Opcodes.ACC_INTERFACE | asm.Opcodes.ACC_ABSTRACT | asm.Opcodes.ACC_FINAL) // ----------------------------------------------------------------------------------------- // factory methods @@ -648,11 +648,12 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { // sort them so inner classes succeed their enclosing class to satisfy the Eclipse Java compiler for (innerSym <- allInners sortBy (_.name.length)) { // TODO why not sortBy (_.name.toString()) ?? - val flags = mkFlags( + val flagsWithFinal: Int = mkFlags( if (innerSym.rawowner.hasModuleFlag) asm.Opcodes.ACC_STATIC else 0, javaFlags(innerSym), if(isDeprecated(innerSym)) asm.Opcodes.ACC_DEPRECATED else 0 // ASM pseudo-access flag ) & (INNER_CLASSES_FLAGS | asm.Opcodes.ACC_DEPRECATED) + val flags = if (innerSym.isModuleClass) flagsWithFinal & ~asm.Opcodes.ACC_FINAL else flagsWithFinal // For SI-5676, object overriding. val jname = javaName(innerSym) // never null val oname = outerName(innerSym) // null when method-enclosed val iname = innerName(innerSym) // null for anonymous inner class diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index b53efafdd4..8e79b56814 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -144,6 +144,15 @@ trait Implicits { private val infoMapCache = new LinkedHashMap[Symbol, InfoMap] private val improvesCache = perRunCaches.newMap[(ImplicitInfo, ImplicitInfo), Boolean]() + private def isInvalidConversionTarget(tpe: Type): Boolean = tpe match { + case Function1(_, out) => AnyRefClass.tpe <:< out + case _ => false + } + private def isInvalidConversionSource(tpe: Type): Boolean = tpe match { + case Function1(in, _) => in <:< NullClass.tpe + case _ => false + } + def resetImplicits() { implicitsCache.clear() infoMapCache.clear() @@ -1357,10 +1366,10 @@ trait Implicits { val wasAmbigious = result.isAmbiguousFailure // SI-6667, never search companions after an ambiguous error in in-scope implicits result = materializeImplicit(pt) - // `materializeImplicit` does some preprocessing for `pt` // is it only meant for manifests/tags or we need to do the same for `implicitsOfExpectedType`? - if (result.isFailure && !wasAmbigious) result = searchImplicit(implicitsOfExpectedType, isLocal = false) + if (result.isFailure && !wasAmbigious) + result = searchImplicit(implicitsOfExpectedType, isLocal = false) if (result.isFailure) { context.updateBuffer(previousErrs) @@ -1370,9 +1379,18 @@ trait Implicits { if (Statistics.canEnable) Statistics.incCounter(oftypeImplicitHits) } } - - if (result.isFailure && settings.debug) - log("no implicits found for "+pt+" "+pt.typeSymbol.info.baseClasses+" "+implicitsOfExpectedType) + if (result.isSuccess && isView) { + if (isInvalidConversionTarget(pt)) { + context.issueAmbiguousError(AmbiguousImplicitTypeError(tree, "the result type of an implicit conversion must be more specific than AnyRef")) + result = SearchFailure + } + else if (isInvalidConversionSource(pt)) { + context.issueAmbiguousError(AmbiguousImplicitTypeError(tree, "an expression of type Null is ineligible for implicit conversion")) + result = SearchFailure + } + } + if (result.isFailure) + debuglog("no implicits found for "+pt+" "+pt.typeSymbol.info.baseClasses+" "+implicitsOfExpectedType) result } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 8d422f415d..cb3a12b60d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1573,9 +1573,9 @@ trait Typers extends Adaptations with Tags { } typedType(decodedtpt) } else { - var supertpt = typedTypeConstructor(decodedtpt) + val supertpt = typedTypeConstructor(decodedtpt) val supertparams = if (supertpt.hasSymbolField) supertpt.symbol.typeParams else Nil - if (supertparams.nonEmpty) { + def inferParentTypeArgs: Tree = { typedPrimaryConstrBody(templ) { val supertpe = PolyType(supertparams, appliedType(supertpt.tpe, supertparams map (_.tpeHK))) val supercall = New(supertpe, mmap(argss)(_.duplicate)) @@ -1583,14 +1583,17 @@ trait Typers extends Adaptations with Tags { ctor setType supertpe // this is an essential hack, otherwise it will occasionally fail to typecheck atPos(supertpt.pos.focus)(supercall) } match { - case EmptyTree => MissingTypeArgumentsParentTpeError(supertpt) - case tpt => supertpt = TypeTree(tpt.tpe) setPos supertpt.pos // SI-7224: don't .focus positions of the TypeTree of a parent that exists in source + case EmptyTree => MissingTypeArgumentsParentTpeError(supertpt); supertpt + case tpt => TypeTree(tpt.tpe) setPos supertpt.pos // SI-7224: don't .focus positions of the TypeTree of a parent that exists in source } } + + val supertptWithTargs = if (supertparams.isEmpty || context.unit.isJava) supertpt else inferParentTypeArgs + // this is the place where we tell the typer what argss should be used for the super call // if argss are nullary or empty, then (see the docs for `typedPrimaryConstrBody`) // the super call dummy is already good enough, so we don't need to do anything - if (argssAreTrivial) supertpt else supertpt updateAttachment SuperArgsAttachment(argss) + if (argssAreTrivial) supertptWithTargs else supertptWithTargs updateAttachment SuperArgsAttachment(argss) } } @@ -5111,7 +5114,7 @@ trait Typers extends Adaptations with Tags { if (mode.inPatternMode) { val uncheckedTypeExtractor = extractorForUncheckedType(tpt.pos, tptTyped.tpe) // make fully defined to avoid bounded wildcard types that may be in pt from calling dropExistential (SI-2038) - val ptDefined = ensureFullyDefined(pt) + val ptDefined = ensureFullyDefined(pt) // FIXME this is probably redundant now that we don't dropExistenial in pattern mode. val ownType = inferTypedPattern(tptTyped, tptTyped.tpe, ptDefined, canRemedy = uncheckedTypeExtractor.nonEmpty) treeTyped setType ownType @@ -5345,7 +5348,12 @@ trait Typers extends Adaptations with Tags { "context.owner" -> context.owner ) ) - typed1(tree, mode, dropExistential(ptPlugins)) + val ptWild = if (mode.inPatternMode) + ptPlugins // SI-5022 don't widen pt for patterns as types flow from it to the case body. + else + dropExistential(ptPlugins) // FIXME: document why this is done. + + typed1(tree, mode, ptWild) } // Can happen during erroneous compilation - error(s) have been // reported, but we need to avoid causing an NPE with this tree diff --git a/src/eclipse/README.md b/src/eclipse/README.md index 73aa270b77..2bb1a4da8f 100644 --- a/src/eclipse/README.md +++ b/src/eclipse/README.md @@ -11,6 +11,9 @@ IMPORTANT Preferences/General/Workspace/Linked Resources. The value should be the absolute path to your scala checkout. All paths in project files are relative to this one, so nothing will work before you do so. +Additionally, we start using Maven dependencies (e.g. junit) so you need to define +`classpath variable` inside Eclipse. Define `M2_REPO` in Java/Build Path/Classpath Variables +to point to your local Maven repository (e.g. $HOME/.m2/repository). 2. The Eclipse Java compiler does not allow certain calls to restricted APIs in the JDK. The Scala library uses such APIs, so you'd see this error: diff --git a/src/eclipse/test-junit/.classpath b/src/eclipse/test-junit/.classpath new file mode 100644 index 0000000000..718f7b6ece --- /dev/null +++ b/src/eclipse/test-junit/.classpath @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="test-junit"/> + <classpathentry combineaccessrules="false" kind="src" path="/reflect"/> + <classpathentry combineaccessrules="false" kind="src" path="/scala-library"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> + <classpathentry kind="lib" path="lib/ant/ant.jar"/> + <classpathentry kind="lib" path="lib/jline.jar"/> + <classpathentry combineaccessrules="false" kind="src" path="/scala-compiler"/> + <classpathentry kind="var" path="M2_REPO/junit/junit/4.10/junit-4.10.jar"/> + <classpathentry kind="output" path="build-test-junit"/> +</classpath> diff --git a/src/eclipse/test-junit/.project b/src/eclipse/test-junit/.project new file mode 100644 index 0000000000..052b6c1b6f --- /dev/null +++ b/src/eclipse/test-junit/.project @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>test-junit</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.scala-ide.sdt.core.scalabuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.scala-ide.sdt.core.scalanature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> + <linkedResources> + <link> + <name>build-test-junit</name> + <type>2</type> + <locationURI>SCALA_BASEDIR/build/junit/classes</locationURI> + </link> + <link> + <name>lib</name> + <type>2</type> + <locationURI>SCALA_BASEDIR/lib</locationURI> + </link> + <link> + <name>test-junit</name> + <type>2</type> + <locationURI>SCALA_BASEDIR/test/junit</locationURI> + </link> + </linkedResources> +</projectDescription> diff --git a/src/library/scala/Option.scala b/src/library/scala/Option.scala index 4b071166c7..905e925f57 100644 --- a/src/library/scala/Option.scala +++ b/src/library/scala/Option.scala @@ -128,7 +128,7 @@ sealed abstract class Option[+A] extends Product with Serializable { * val textField = new JComponent(initalText.orNull,20) * }}} */ - @inline final def orNull[A1 >: A](implicit ev: Null <:< A1): A1 = this getOrElse null + @inline final def orNull[A1 >: A](implicit ev: Null <:< A1): A1 = this getOrElse ev(null) /** Returns a $some containing the result of applying $f to this $option's * value if this $option is nonempty. @@ -210,7 +210,7 @@ sealed abstract class Option[+A] extends Product with Serializable { } /** Tests whether the option contains a given value as an element. - * + * * @param elem the element to test. * @return `true` if the option has an element that is equal (as * determined by `==`) to `elem`, `false` otherwise. diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index 569157de20..5ba38600b6 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -346,19 +346,6 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { implicit def double2Double(x: Double) = java.lang.Double.valueOf(x) implicit def boolean2Boolean(x: Boolean) = java.lang.Boolean.valueOf(x) - // These next eight implicits exist solely to exclude AnyRef methods from the - // eight implicits above so that primitives are not coerced to AnyRefs. They - // only create such conflict for AnyRef methods, so the methods on the java.lang - // boxed types are unambiguously reachable. - implicit def byte2ByteConflict(x: Byte) = new AnyRef - implicit def short2ShortConflict(x: Short) = new AnyRef - implicit def char2CharacterConflict(x: Char) = new AnyRef - implicit def int2IntegerConflict(x: Int) = new AnyRef - implicit def long2LongConflict(x: Long) = new AnyRef - implicit def float2FloatConflict(x: Float) = new AnyRef - implicit def double2DoubleConflict(x: Double) = new AnyRef - implicit def boolean2BooleanConflict(x: Boolean) = new AnyRef - implicit def Byte2byte(x: java.lang.Byte): Byte = x.byteValue implicit def Short2short(x: java.lang.Short): Short = x.shortValue implicit def Character2char(x: java.lang.Character): Char = x.charValue @@ -481,24 +468,6 @@ private[scala] abstract class LowPriorityImplicits { @inline implicit def doubleWrapper(x: Double) = new runtime.RichDouble(x) @inline implicit def booleanWrapper(x: Boolean) = new runtime.RichBoolean(x) - // These eight implicits exist solely to exclude Null from the domain of - // the boxed types, so that e.g. "var x: Int = null" is a compile time - // error rather than a delayed null pointer exception by way of the - // conversion from java.lang.Integer. If defined in the same template as - // Integer2int, they would have higher priority because Null is a subtype - // of Integer. We balance that out and create conflict by moving the - // definition into the superclass. - // - // Caution: do not adjust tightrope tension without safety goggles in place. - implicit def Byte2byteNullConflict(x: Null): Byte = sys.error("value error") - implicit def Short2shortNullConflict(x: Null): Short = sys.error("value error") - implicit def Character2charNullConflict(x: Null): Char = sys.error("value error") - implicit def Integer2intNullConflict(x: Null): Int = sys.error("value error") - implicit def Long2longNullConflict(x: Null): Long = sys.error("value error") - implicit def Float2floatNullConflict(x: Null): Float = sys.error("value error") - implicit def Double2doubleNullConflict(x: Null): Double = sys.error("value error") - implicit def Boolean2booleanNullConflict(x: Null): Boolean = sys.error("value error") - implicit def genericWrapArray[T](xs: Array[T]): WrappedArray[T] = if (xs eq null) null else WrappedArray.make(xs) diff --git a/src/library/scala/concurrent/duration/Duration.scala b/src/library/scala/concurrent/duration/Duration.scala index a24266bf19..9a8844b489 100644 --- a/src/library/scala/concurrent/duration/Duration.scala +++ b/src/library/scala/concurrent/duration/Duration.scala @@ -221,6 +221,8 @@ object Duration { final def toMinutes: Long = fail("toMinutes") final def toHours: Long = fail("toHours") final def toDays: Long = fail("toDays") + + final def toCoarsest: Duration = this } /** @@ -520,6 +522,18 @@ sealed abstract class Duration extends Serializable with Ordered[Duration] { * $ovf */ def plus(other: Duration) = this + other + /** + * Return duration which is equal to this duration but with a coarsest Unit, or self in case it is already the coarsest Unit + * <p/> + * Examples: + * {{{ + * Duration(60, MINUTES).toCoarsest // Duration(1, HOURS) + * Duration(1000, MILLISECONDS).toCoarsest // Duration(1, SECONDS) + * Duration(48, HOURS).toCoarsest // Duration(2, DAYS) + * Duration(5, SECONDS).toCoarsest // Duration(5, SECONDS) + * }}} + */ + def toCoarsest: Duration } object FiniteDuration { @@ -691,6 +705,28 @@ final class FiniteDuration(val length: Long, val unit: TimeUnit) extends Duratio final def isFinite() = true + final def toCoarsest: Duration = { + def loop(length: Long, unit: TimeUnit): FiniteDuration = { + def coarserOrThis(coarser: TimeUnit, divider: Int) = + if (length % divider == 0) loop(length / divider, coarser) + else if (unit == this.unit) this + else FiniteDuration(length, unit) + + unit match { + case DAYS => FiniteDuration(length, unit) + case HOURS => coarserOrThis(DAYS, 24) + case MINUTES => coarserOrThis(HOURS, 60) + case SECONDS => coarserOrThis(MINUTES, 60) + case MILLISECONDS => coarserOrThis(SECONDS, 1000) + case MICROSECONDS => coarserOrThis(MILLISECONDS, 1000) + case NANOSECONDS => coarserOrThis(MICROSECONDS, 1000) + } + } + + if (unit == DAYS || length == 0) this + else loop(length, unit) + } + override def equals(other: Any) = other match { case x: FiniteDuration => toNanos == x.toNanos case _ => super.equals(other) diff --git a/src/library/scala/util/Properties.scala b/src/library/scala/util/Properties.scala index 2240dde360..fef9cef246 100644 --- a/src/library/scala/util/Properties.scala +++ b/src/library/scala/util/Properties.scala @@ -146,6 +146,9 @@ private[scala] trait PropertiesTrait { /** Returns `true` iff the underlying operating system is a version of Apple Mac OSX. */ def isMac = osName startsWith "Mac OS X" + /* Some runtime values. */ + private[scala] def isAvian = javaVmName contains "Avian" + // This is looking for javac, tools.jar, etc. // Tries JDK_HOME first, then the more common but likely jre JAVA_HOME, // and finally the system property based javaHome. diff --git a/src/partest/scala/tools/partest/nest/Runner.scala b/src/partest/scala/tools/partest/nest/Runner.scala index 1034d724d2..a53698eb77 100644 --- a/src/partest/scala/tools/partest/nest/Runner.scala +++ b/src/partest/scala/tools/partest/nest/Runner.scala @@ -286,7 +286,7 @@ class Runner(val testFile: File, fileManager: FileManager, val testRunParams: Te * might be failing, in the normal case. */ def diffilter(d: String) = { - import scala.util.Properties.javaVersion + import scala.util.Properties.{javaVersion, isAvian} val prefix = "#partest" val margin = "> " val leader = margin + prefix @@ -297,6 +297,7 @@ class Runner(val testFile: File, fileManager: FileManager, val testRunParams: Te val cond = token match { case "java7" => javaVersion startsWith "1.7" case "java6" => javaVersion startsWith "1.6" + case "avian" => isAvian case "true" => true case _ => false } diff --git a/src/partest/scala/tools/partest/utils/Properties.scala b/src/partest/scala/tools/partest/utils/Properties.scala index 1263c96e9e..b9394b50c9 100644 --- a/src/partest/scala/tools/partest/utils/Properties.scala +++ b/src/partest/scala/tools/partest/utils/Properties.scala @@ -14,4 +14,5 @@ package utils object Properties extends scala.util.PropertiesTrait { protected def propCategory = "partest" protected def pickJarBasedOn = classOf[nest.RunnerManager] + override def isAvian = super.isAvian } diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 2da9fa1cca..c3596fe62e 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -752,7 +752,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isMonomorphicType = isType && { val info = originalInfo - info.isComplete && !info.isHigherKinded + ( (info eq null) + || (info.isComplete && !info.isHigherKinded) + ) } def isStrictFP = hasAnnotation(ScalaStrictFPAttr) || (enclClass hasAnnotation ScalaStrictFPAttr) diff --git a/test/files/neg/no-implicit-to-anyref.check b/test/files/neg/no-implicit-to-anyref.check index d94b57a30a..fe417ad8b0 100644 --- a/test/files/neg/no-implicit-to-anyref.check +++ b/test/files/neg/no-implicit-to-anyref.check @@ -1,10 +1,4 @@ -no-implicit-to-anyref.scala:11: error: type mismatch; - found : Int(1) - required: AnyRef -Note: an implicit exists from scala.Int => java.lang.Integer, but -methods inherited from Object are rendered ambiguous. This is to avoid -a blanket implicit which would convert any scala.Int to any AnyRef. -You may wish to use a type ascription: `x: java.lang.Integer`. +no-implicit-to-anyref.scala:11: error: the result type of an implicit conversion must be more specific than AnyRef 1: AnyRef ^ no-implicit-to-anyref.scala:17: error: type mismatch; diff --git a/test/files/neg/t4158.check b/test/files/neg/t4158.check index 3ee2627c5b..af281c52cd 100644 --- a/test/files/neg/t4158.check +++ b/test/files/neg/t4158.check @@ -1,19 +1,7 @@ -t4158.scala:3: error: type mismatch; - found : Null(null) - required: Int -Note that implicit conversions are not applicable because they are ambiguous: - both method Integer2intNullConflict in class LowPriorityImplicits of type (x: Null)Int - and method Integer2int in object Predef of type (x: Integer)Int - are possible conversion functions from Null(null) to Int +t4158.scala:3: error: an expression of type Null is ineligible for implicit conversion var y = null: Int ^ -t4158.scala:2: error: type mismatch; - found : Null(null) - required: Int -Note that implicit conversions are not applicable because they are ambiguous: - both method Integer2intNullConflict in class LowPriorityImplicits of type (x: Null)Int - and method Integer2int in object Predef of type (x: Integer)Int - are possible conversion functions from Null(null) to Int +t4158.scala:2: error: an expression of type Null is ineligible for implicit conversion var x: Int = null ^ two errors found diff --git a/test/files/neg/t4515.check b/test/files/neg/t4515.check index a60d16295f..64e7cc1ca7 100644 --- a/test/files/neg/t4515.check +++ b/test/files/neg/t4515.check @@ -1,6 +1,6 @@ t4515.scala:37: error: type mismatch; - found : _0(in value $anonfun) where type _0(in value $anonfun) - required: (some other)_0(in value $anonfun) + found : _$1 where type _$1 + required: _$2 handler.onEvent(target, ctx.getEvent, node, ctx) ^ one error found diff --git a/test/files/neg/t4727.check b/test/files/neg/t4727.check index 8a4536fec3..a17cdde044 100644 --- a/test/files/neg/t4727.check +++ b/test/files/neg/t4727.check @@ -1,10 +1,4 @@ -t4727.scala:5: error: type mismatch; - found : Null - required: Int -Note that implicit conversions are not applicable because they are ambiguous: - both method Integer2intNullConflict in class LowPriorityImplicits of type (x: Null)Int - and method Integer2int in object Predef of type (x: Integer)Int - are possible conversion functions from Null to Int +t4727.scala:5: error: an expression of type Null is ineligible for implicit conversion Error occurred in an application involving default arguments. new C[Int] ^ diff --git a/test/files/neg/t6889.check b/test/files/neg/t6889.check new file mode 100644 index 0000000000..a77e8a010c --- /dev/null +++ b/test/files/neg/t6889.check @@ -0,0 +1,7 @@ +t6889.scala:16: error: the result type of an implicit conversion must be more specific than AnyRef + def f(x: Dingo): AnyRef = x // fail - no conversion to AnyRef + ^ +t6889.scala:17: error: an expression of type Null is ineligible for implicit conversion + var x: Int = null // fail - no conversion from Null + ^ +two errors found diff --git a/test/files/neg/t6889.scala b/test/files/neg/t6889.scala new file mode 100644 index 0000000000..ef1963669c --- /dev/null +++ b/test/files/neg/t6889.scala @@ -0,0 +1,18 @@ +package bippy { + trait Bippy[A] extends Any +} +package foo { + package object unrelated { + implicit def bippyDingo[A](x: bippy.Bippy[A]): AnyRef = Nil + } + package unrelated { + trait Unrelated + } +} + +object Test { + trait Dingo extends Any with bippy.Bippy[foo.unrelated.Unrelated] + + def f(x: Dingo): AnyRef = x // fail - no conversion to AnyRef + var x: Int = null // fail - no conversion from Null +} diff --git a/test/files/neg/t7292-deprecation.check b/test/files/neg/t7292-deprecation.check new file mode 100644 index 0000000000..17f010dfdf --- /dev/null +++ b/test/files/neg/t7292-deprecation.check @@ -0,0 +1,12 @@ +t7292-deprecation.scala:2: warning: Octal escape literals are deprecated, use \u0000 instead. + val chr1 = '\0' + ^ +t7292-deprecation.scala:3: warning: Octal escape literals are deprecated, use \u0053 instead. + val str1 = "abc\123456" + ^ +t7292-deprecation.scala:4: warning: Octal escape literals are deprecated, use \n instead. + val lf = '\012' + ^ +error: No warnings can be incurred under -Xfatal-warnings. +three warnings found +one error found diff --git a/test/files/neg/t7292-deprecation.flags b/test/files/neg/t7292-deprecation.flags new file mode 100644 index 0000000000..7de3c0f3ee --- /dev/null +++ b/test/files/neg/t7292-deprecation.flags @@ -0,0 +1 @@ +-Xfatal-warnings -deprecation diff --git a/test/files/neg/t7292-deprecation.scala b/test/files/neg/t7292-deprecation.scala new file mode 100644 index 0000000000..d857f0e1ec --- /dev/null +++ b/test/files/neg/t7292-deprecation.scala @@ -0,0 +1,5 @@ +object OctalEscapes { + val chr1 = '\0' + val str1 = "abc\123456" + val lf = '\012' +} diff --git a/test/files/neg/t7292-removal.check b/test/files/neg/t7292-removal.check new file mode 100644 index 0000000000..1cd59b0992 --- /dev/null +++ b/test/files/neg/t7292-removal.check @@ -0,0 +1,10 @@ +t7292-removal.scala:2: error: Octal escape literals are unsupported, use \u0000 instead. + val chr1 = '\0' + ^ +t7292-removal.scala:3: error: Octal escape literals are unsupported, use \u0053 instead. + val str1 = "abc\123456" + ^ +t7292-removal.scala:4: error: Octal escape literals are unsupported, use \n instead. + val lf = '\012' + ^ +three errors found diff --git a/test/files/neg/t7292-removal.flags b/test/files/neg/t7292-removal.flags new file mode 100644 index 0000000000..29f4ede37a --- /dev/null +++ b/test/files/neg/t7292-removal.flags @@ -0,0 +1 @@ +-Xfuture diff --git a/test/files/neg/t7292-removal.scala b/test/files/neg/t7292-removal.scala new file mode 100644 index 0000000000..d857f0e1ec --- /dev/null +++ b/test/files/neg/t7292-removal.scala @@ -0,0 +1,5 @@ +object OctalEscapes { + val chr1 = '\0' + val str1 = "abc\123456" + val lf = '\012' +} diff --git a/test/files/pos/t2613.scala b/test/files/pos/t2613.scala new file mode 100644 index 0000000000..3a64dbc282 --- /dev/null +++ b/test/files/pos/t2613.scala @@ -0,0 +1,11 @@ +import language.existentials + +object Test { + class Row + + abstract class MyRelation [R <: Row, +Relation <: MyRelation[R, Relation]] + + type M = MyRelation[R, Relation] forSome {type R <: Row; type Relation <: MyRelation[R, Relation]} + + var (x,y): (String, M) = null +} diff --git a/test/files/pos/t5022.scala b/test/files/pos/t5022.scala new file mode 100644 index 0000000000..b9a085fb35 --- /dev/null +++ b/test/files/pos/t5022.scala @@ -0,0 +1,22 @@ +class ForSomeVsUnapply { + def test { + def makeWrap: Wrap = ??? + def useRep[e](rep: (e, X[e])) = () + + val repUnapply = Wrap.unapply(makeWrap).get + useRep(repUnapply) // okay + + val Wrap(rep0) = makeWrap + useRep(rep0) // error + + val rep = makeWrap match { + case Wrap(r) => r + }; + + useRep(rep) // error + } +} + +class X[e] + +case class Wrap(rep: (e, X[e]) forSome { type e }) diff --git a/test/files/pos/t7364/BadList.java b/test/files/pos/t7364/BadList.java new file mode 100644 index 0000000000..2692fa085f --- /dev/null +++ b/test/files/pos/t7364/BadList.java @@ -0,0 +1,3 @@ +public class BadList extends java.util.ArrayList { + public java.util.ArrayList foo() { return null; } +} diff --git a/test/files/pos/t7364/UseIt.scala b/test/files/pos/t7364/UseIt.scala new file mode 100644 index 0000000000..3847165323 --- /dev/null +++ b/test/files/pos/t7364/UseIt.scala @@ -0,0 +1,4 @@ +class UseIt { + val list = new BadList + list.foo() +} diff --git a/test/files/pos/t7364b/BadList_1.java b/test/files/pos/t7364b/BadList_1.java new file mode 100644 index 0000000000..fbb428adba --- /dev/null +++ b/test/files/pos/t7364b/BadList_1.java @@ -0,0 +1,3 @@ +public class BadList_1 extends java.util.ArrayList { + public java.util.ArrayList foo() { return null; } +} diff --git a/test/files/pos/t7364b/UseIt_2.scala b/test/files/pos/t7364b/UseIt_2.scala new file mode 100644 index 0000000000..06b50f6766 --- /dev/null +++ b/test/files/pos/t7364b/UseIt_2.scala @@ -0,0 +1,5 @@ +class UseIt { + val list = new BadList_1 + list.foo() + list.set(0, list.get(0)) +} diff --git a/test/files/run/WeakHashSetTest.scala b/test/files/run/WeakHashSetTest.scala deleted file mode 100644 index 3c8f380150..0000000000 --- a/test/files/run/WeakHashSetTest.scala +++ /dev/null @@ -1,174 +0,0 @@ -object Test { - def main(args: Array[String]) { - val test = scala.reflect.internal.util.WeakHashSetTest - test.checkEmpty - test.checkPlusEquals - test.checkPlusEqualsCollisions - test.checkRehashing - test.checkRehashCollisions - test.checkFindOrUpdate - test.checkMinusEquals - test.checkMinusEqualsCollisions - test.checkClear - test.checkIterator - test.checkIteratorCollisions - - // This test is commented out because it relies on gc behavior which isn't reliable enough in an automated environment - // test.checkRemoveUnreferencedObjects - } -} - -// put the main test object in the same package as WeakHashSet because -// it uses the package private "diagnostics" method -package scala.reflect.internal.util { - - object WeakHashSetTest { - // a class guaranteed to provide hash collisions - case class Collider(x : String) extends Comparable[Collider] with Serializable { - override def hashCode = 0 - def compareTo(y : Collider) = this.x compareTo y.x - } - - // basic emptiness check - def checkEmpty { - val hs = new WeakHashSet[String]() - assert(hs.size == 0) - hs.diagnostics.fullyValidate - } - - // make sure += works - def checkPlusEquals { - val hs = new WeakHashSet[String]() - val elements = List("hello", "goodbye") - elements foreach (hs += _) - assert(hs.size == 2) - assert(hs contains "hello") - assert(hs contains "goodbye") - hs.diagnostics.fullyValidate - } - - // make sure += works when there are collisions - def checkPlusEqualsCollisions { - val hs = new WeakHashSet[Collider]() - val elements = List("hello", "goodbye") map Collider - elements foreach (hs += _) - assert(hs.size == 2) - assert(hs contains Collider("hello")) - assert(hs contains Collider("goodbye")) - hs.diagnostics.fullyValidate - } - - // add a large number of elements to force rehashing and then validate - def checkRehashing { - val size = 200 - val hs = new WeakHashSet[String]() - val elements = (0 until size).toList map ("a" + _) - elements foreach (hs += _) - elements foreach {i => assert(hs contains i)} - hs.diagnostics.fullyValidate - } - - // make sure rehashing works properly when the set is rehashed - def checkRehashCollisions { - val size = 200 - val hs = new WeakHashSet[Collider]() - val elements = (0 until size).toList map {x => Collider("a" + x)} - elements foreach (hs += _) - elements foreach {i => assert(hs contains i)} - hs.diagnostics.fullyValidate - } - - // test that unreferenced objects are removed - // not run in an automated environment because gc behavior can't be relied on - def checkRemoveUnreferencedObjects { - val size = 200 - val hs = new WeakHashSet[Collider]() - val elements = (0 until size).toList map {x => Collider("a" + x)} - elements foreach (hs += _) - // don't throw the following into a retained collection so gc - // can remove them - for (i <- 0 until size) { - hs += Collider("b" + i) - } - System.gc() - Thread.sleep(1000) - assert(hs.size == 200) - elements foreach {i => assert(hs contains i)} - for (i <- 0 until size) { - assert(!(hs contains Collider("b" + i))) - } - hs.diagnostics.fullyValidate - } - - // make sure findOrUpdate returns the originally entered element - def checkFindOrUpdate { - val size = 200 - val hs = new WeakHashSet[Collider]() - val elements = (0 until size).toList map {x => Collider("a" + x)} - elements foreach {x => assert(hs findEntryOrUpdate x eq x)} - for (i <- 0 until size) { - // when we do a lookup the result should be the same reference we - // original put in - assert(hs findEntryOrUpdate(Collider("a" + i)) eq elements(i)) - } - hs.diagnostics.fullyValidate - } - - // check -= functionality - def checkMinusEquals { - val hs = new WeakHashSet[String]() - val elements = List("hello", "goodbye") - elements foreach (hs += _) - hs -= "goodbye" - assert(hs.size == 1) - assert(hs contains "hello") - assert(!(hs contains "goodbye")) - hs.diagnostics.fullyValidate - } - - // check -= when there are collisions - def checkMinusEqualsCollisions { - val hs = new WeakHashSet[Collider] - val elements = List(Collider("hello"), Collider("goodbye")) - elements foreach (hs += _) - hs -= Collider("goodbye") - assert(hs.size == 1) - assert(hs contains Collider("hello")) - assert(!(hs contains Collider("goodbye"))) - hs -= Collider("hello") - assert(hs.size == 0) - assert(!(hs contains Collider("hello"))) - hs.diagnostics.fullyValidate - } - - // check that the clear method actually cleans everything - def checkClear { - val size = 200 - val hs = new WeakHashSet[String]() - val elements = (0 until size).toList map ("a" + _) - elements foreach (hs += _) - hs.clear() - assert(hs.size == 0) - elements foreach {i => assert(!(hs contains i))} - hs.diagnostics.fullyValidate - } - - // check that the iterator covers all the contents - def checkIterator { - val hs = new WeakHashSet[String]() - val elements = (0 until 20).toList map ("a" + _) - elements foreach (hs += _) - assert(elements.iterator.toList.sorted == elements.sorted) - hs.diagnostics.fullyValidate - } - - // check that the iterator covers all the contents even when there is a collision - def checkIteratorCollisions { - val hs = new WeakHashSet[Collider] - val elements = (0 until 20).toList map {x => Collider("a" + x)} - elements foreach (hs += _) - assert(elements.iterator.toList.sorted == elements.sorted) - hs.diagnostics.fullyValidate - } - } -} diff --git a/test/files/run/duration-coarsest.scala b/test/files/run/duration-coarsest.scala new file mode 100644 index 0000000000..51cb79287a --- /dev/null +++ b/test/files/run/duration-coarsest.scala @@ -0,0 +1,28 @@ +import scala.concurrent.duration._ +import scala.language.postfixOps + +object Test extends App { + List( + (60 minutes, 1 hour), + (2000 millis, 2 seconds), + (2000 micros, 2 millis), + (2000 nanos, 2 micros), + (2000000 nanos, 2 millis), + (48 hours, 2 days), + (5 seconds, 5 seconds), + (1 second, 1 second) + ) foreach { + case (x, expected) => + val actual = x.toCoarsest + assert(actual.unit == expected.unit, s"$actual, $expected") + assert(actual.length == expected.length, s"$actual, $expected") + } + + List( + 45 minutes, + 500 millis, + 1500 millis, + 23 hours, + 40 days + ) foreach (x => assert(x == x.toCoarsest, x)) +}
\ No newline at end of file diff --git a/test/files/run/literals.check b/test/files/run/literals.check index 6be5137994..5f948762b7 100644 --- a/test/files/run/literals.check +++ b/test/files/run/literals.check @@ -1,4 +1,4 @@ -warning: there were 13 deprecation warning(s); re-run with -deprecation for details +warning: there were 18 deprecation warning(s); re-run with -deprecation for details test '\u0024' == '$' was successful test '\u005f' == '_' was successful test 65.asInstanceOf[Char] == 'A' was successful diff --git a/test/files/run/richs.check b/test/files/run/richs.check index a970a814b1..02a98b376d 100644 --- a/test/files/run/richs.check +++ b/test/files/run/richs.check @@ -1,3 +1,4 @@ +warning: there were 2 deprecation warning(s); re-run with -deprecation for details RichCharTest1: true diff --git a/test/files/run/t5313.scala b/test/files/run/t5313.scala index 7da8726a1f..febfd9c3ed 100644 --- a/test/files/run/t5313.scala +++ b/test/files/run/t5313.scala @@ -7,7 +7,7 @@ object Test extends IcodeTest { override def code = """class Foo { - def randomBoolean = util.Random.nextInt % 2 == 0 + def randomBoolean = scala.util.Random.nextInt % 2 == 0 def bar = { var kept1 = new Object val result = new java.lang.ref.WeakReference(kept1) diff --git a/test/files/run/t7151.check b/test/files/run/t7151.check new file mode 100644 index 0000000000..d532d9589f --- /dev/null +++ b/test/files/run/t7151.check @@ -0,0 +1,6 @@ +class Test$InnerObject$ isFinal = false +class Test$InnerCase isFinal = true +class Test$InnerNonCase isFinal = true +class TopLevelObject$ isFinal = true +class TopLevelCase isFinal = true +class TopLevelNonCase isFinal = true diff --git a/test/files/run/t7151.scala b/test/files/run/t7151.scala new file mode 100644 index 0000000000..f6492ba43c --- /dev/null +++ b/test/files/run/t7151.scala @@ -0,0 +1,24 @@ +import java.lang.reflect.Modifier.isFinal + +object Test { + object InnerObject + final case class InnerCase() + final class InnerNonCase() + + def main(args: Array[String]) { + def checkFinal(clazz: Class[_]) = + println(s"${clazz} isFinal = ${isFinal(clazz.getModifiers())}") + + checkFinal(InnerObject.getClass) + checkFinal(classOf[InnerCase]) + checkFinal(classOf[InnerNonCase]) + + checkFinal(TopLevelObject.getClass) + checkFinal(classOf[TopLevelCase]) + checkFinal(classOf[TopLevelNonCase]) + } +} + +object TopLevelObject +final case class TopLevelCase() +final case class TopLevelNonCase() diff --git a/test/files/run/t7439.check b/test/files/run/t7439.check new file mode 100644 index 0000000000..9ea09f9c40 --- /dev/null +++ b/test/files/run/t7439.check @@ -0,0 +1,2 @@ +Recompiling after deleting t7439-run.obj/A_1.class +pos: NoPosition Class A_1 not found - continuing with a stub. WARNING diff --git a/test/files/run/t7439/A_1.java b/test/files/run/t7439/A_1.java new file mode 100644 index 0000000000..4accd95d57 --- /dev/null +++ b/test/files/run/t7439/A_1.java @@ -0,0 +1,3 @@ +public class A_1 { + +}
\ No newline at end of file diff --git a/test/files/run/t7439/B_1.java b/test/files/run/t7439/B_1.java new file mode 100644 index 0000000000..5dd3b93d6f --- /dev/null +++ b/test/files/run/t7439/B_1.java @@ -0,0 +1,3 @@ +public class B_1 { + public void b(A_1[] a) {} +} diff --git a/test/files/run/t7439/Test_2.scala b/test/files/run/t7439/Test_2.scala new file mode 100644 index 0000000000..3ebbcfe753 --- /dev/null +++ b/test/files/run/t7439/Test_2.scala @@ -0,0 +1,32 @@ +import scala.tools.partest._ +import java.io.File + +object Test extends StoreReporterDirectTest { + def code = ??? + + def compileCode(code: String) = { + val classpath = List(sys.props("partest.lib"), testOutput.path) mkString sys.props("path.separator") + compileString(newCompiler("-cp", classpath, "-d", testOutput.path))(code) + } + + def C = """ + class C { + new B_1 + } + """ + + def show(): Unit = { + //compileCode(C) + assert(filteredInfos.isEmpty, filteredInfos) + + // blow away the entire package + val a1Class = new File(testOutput.path, "A_1.class") + assert(a1Class.exists) + assert(a1Class.delete()) + println(s"Recompiling after deleting $a1Class") + + // bad symbolic reference error expected (but no stack trace!) + compileCode(C) + println(storeReporter.infos.mkString("\n")) // Included a NullPointerException before. + } +} diff --git a/test/files/run/tailcalls.check b/test/files/run/tailcalls.check index f123bc8f25..10384ac46e 100644 --- a/test/files/run/tailcalls.check +++ b/test/files/run/tailcalls.check @@ -1,3 +1,4 @@ +#partest !avian test Object .f was successful test Final .f was successful test Class .f raised exception java.lang.StackOverflowError @@ -51,3 +52,58 @@ test TailCall.b2 was successful test FancyTailCalls.tcTryLocal was successful test FancyTailCalls.differentInstance was successful test PolyObject.tramp was successful + +#partest avian +test Object .f was successful +test Final .f was successful +test Class .f was successful +test SubClass .f was successful +test Sealed .f was successful +test SubSealed.f was successful + +test O .f was successful +test c .f was successful +test O.O .f was successful +test O.c .f was successful +test c.O .f was successful +test c.c .f was successful +test O.O.O .f was successful +test O.O.c .f was successful +test O.c.O .f was successful +test O.c.c .f was successful +test c.O.O .f was successful +test c.O.c .f was successful +test c.c.O .f was successful +test c.c.c .f was successful +test O.O.O.O.f was successful +test O.O.O.c.f was successful +test O.O.c.O.f was successful +test O.O.c.c.f was successful +test O.c.O.O.f was successful +test O.c.O.c.f was successful +test O.c.c.O.f was successful +test O.c.c.c.f was successful +test c.O.O.O.f was successful +test c.O.O.c.f was successful +test c.O.c.O.f was successful +test c.O.c.c.f was successful +test c.c.O.O.f was successful +test c.c.O.c.f was successful +test c.c.c.O.f was successful +test c.c.c.c.f was successful + +test TailCall.f1 was successful +test TailCall.f2 was successful +test TailCall.f3 was successful +test TailCall.g1 was successful +test TailCall.g2 was successful +test TailCall.g3 was successful +test TailCall.h1 was successful + +test NonTailCall.f1 0 1 2 was successful +test NonTailCall.f2 +test TailCall.b1 was successful +test TailCall.b2 was successful +test FancyTailCalls.tcTryLocal was successful +test FancyTailCalls.differentInstance was successful +test PolyObject.tramp was successful
\ No newline at end of file diff --git a/test/files/run/tailcalls.scala b/test/files/run/tailcalls.scala index 7d06a7e69d..1d4124e138 100644 --- a/test/files/run/tailcalls.scala +++ b/test/files/run/tailcalls.scala @@ -307,7 +307,7 @@ object Test { def main(args: Array[String]) { // compute min and max iteration number val min = 16; - val max = calibrate; + val max = if (scala.tools.partest.utils.Properties.isAvian) 10000 else calibrate // test tail calls in different contexts val Final = new Final() diff --git a/test/junit/scala/reflect/internal/util/WeakHashSetTest.scala b/test/junit/scala/reflect/internal/util/WeakHashSetTest.scala new file mode 100644 index 0000000000..7e3b35c7d6 --- /dev/null +++ b/test/junit/scala/reflect/internal/util/WeakHashSetTest.scala @@ -0,0 +1,171 @@ +package scala.reflect.internal.util + +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@RunWith(classOf[JUnit4]) +class WeakHashSetTest { + + // a class guaranteed to provide hash collisions + case class Collider(x : String) extends Comparable[Collider] with Serializable { + override def hashCode = 0 + def compareTo(y : Collider) = this.x compareTo y.x + } + + // basic emptiness check + @Test + def checkEmpty { + val hs = new WeakHashSet[String]() + assert(hs.size == 0) + hs.diagnostics.fullyValidate + } + + // make sure += works + @Test + def checkPlusEquals { + val hs = new WeakHashSet[String]() + val elements = List("hello", "goodbye") + elements foreach (hs += _) + assert(hs.size == 2) + assert(hs contains "hello") + assert(hs contains "goodbye") + hs.diagnostics.fullyValidate + } + + // make sure += works when there are collisions + @Test + def checkPlusEqualsCollisions { + val hs = new WeakHashSet[Collider]() + val elements = List("hello", "goodbye") map Collider + elements foreach (hs += _) + assert(hs.size == 2) + assert(hs contains Collider("hello")) + assert(hs contains Collider("goodbye")) + hs.diagnostics.fullyValidate + } + + // add a large number of elements to force rehashing and then validate + @Test + def checkRehashing { + val size = 200 + val hs = new WeakHashSet[String]() + val elements = (0 until size).toList map ("a" + _) + elements foreach (hs += _) + elements foreach {i => assert(hs contains i)} + hs.diagnostics.fullyValidate + } + + // make sure rehashing works properly when the set is rehashed + @Test + def checkRehashCollisions { + val size = 200 + val hs = new WeakHashSet[Collider]() + val elements = (0 until size).toList map {x => Collider("a" + x)} + elements foreach (hs += _) + elements foreach {i => assert(hs contains i)} + hs.diagnostics.fullyValidate + } + + // test that unreferenced objects are removed + // not run in an automated environment because gc behavior can't be relied on + //@Test + def checkRemoveUnreferencedObjects { + val size = 200 + val hs = new WeakHashSet[Collider]() + val elements = (0 until size).toList map {x => Collider("a" + x)} + elements foreach (hs += _) + // don't throw the following into a retained collection so gc + // can remove them + for (i <- 0 until size) { + hs += Collider("b" + i) + } + System.gc() + Thread.sleep(1000) + assert(hs.size == 200) + elements foreach {i => assert(hs contains i)} + for (i <- 0 until size) { + assert(!(hs contains Collider("b" + i))) + } + hs.diagnostics.fullyValidate + } + + // make sure findOrUpdate returns the originally entered element + @Test + def checkFindOrUpdate { + val size = 200 + val hs = new WeakHashSet[Collider]() + val elements = (0 until size).toList map {x => Collider("a" + x)} + elements foreach {x => assert(hs findEntryOrUpdate x eq x)} + for (i <- 0 until size) { + // when we do a lookup the result should be the same reference we + // original put in + assert(hs findEntryOrUpdate(Collider("a" + i)) eq elements(i)) + } + hs.diagnostics.fullyValidate + } + + // check -= functionality + @Test + def checkMinusEquals { + val hs = new WeakHashSet[String]() + val elements = List("hello", "goodbye") + elements foreach (hs += _) + hs -= "goodbye" + assert(hs.size == 1) + assert(hs contains "hello") + assert(!(hs contains "goodbye")) + hs.diagnostics.fullyValidate + } + + // check -= when there are collisions + @Test + def checkMinusEqualsCollisions { + val hs = new WeakHashSet[Collider] + val elements = List(Collider("hello"), Collider("goodbye")) + elements foreach (hs += _) + hs -= Collider("goodbye") + assert(hs.size == 1) + assert(hs contains Collider("hello")) + assert(!(hs contains Collider("goodbye"))) + hs -= Collider("hello") + assert(hs.size == 0) + assert(!(hs contains Collider("hello"))) + hs.diagnostics.fullyValidate + } + + // check that the clear method actually cleans everything + @Test + def checkClear { + val size = 200 + val hs = new WeakHashSet[String]() + val elements = (0 until size).toList map ("a" + _) + elements foreach (hs += _) + hs.clear() + assert(hs.size == 0) + elements foreach {i => assert(!(hs contains i))} + hs.diagnostics.fullyValidate + } + + // check that the iterator covers all the contents + @Test + def checkIterator { + val hs = new WeakHashSet[String]() + val elements = (0 until 20).toList map ("a" + _) + elements foreach (hs += _) + assert(elements.iterator.toList.sorted == elements.sorted) + hs.diagnostics.fullyValidate + } + + // check that the iterator covers all the contents even when there is a collision + @Test + def checkIteratorCollisions { + val hs = new WeakHashSet[Collider] + val elements = (0 until 20).toList map {x => Collider("a" + x)} + elements foreach (hs += _) + assert(elements.iterator.toList.sorted == elements.sorted) + hs.diagnostics.fullyValidate + } + +} diff --git a/test/junit/scala/tools/nsc/SampleTest.scala b/test/junit/scala/tools/nsc/SampleTest.scala new file mode 100644 index 0000000000..8e026da1ea --- /dev/null +++ b/test/junit/scala/tools/nsc/SampleTest.scala @@ -0,0 +1,17 @@ +package scala.tools.nsc +package test + +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +/** Sample JUnit test that shows that all pieces + of JUnit infrastructure work correctly */ +@RunWith(classOf[JUnit4]) +class SampleTest { + @Test + def testMath: Unit = { + assert(2+2 == 4, "you didn't get the math right fellow") + } +} |