diff options
82 files changed, 1200 insertions, 358 deletions
@@ -22,7 +22,7 @@ END-USER TARGETS <target name="clean" depends="quick.clean" description="Removes binaries of compiler and library. Distributions are untouched."/> - <target name="test" depends="test.done" + <target name="test" depends="test.done, osgi.test" description="Runs test suite and bootstrapping test on Scala compiler and library."/> <target name="test-opt" @@ -217,6 +217,7 @@ PROPERTIES <property name="build-palo.dir" value="${build.dir}/palo"/> <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-strap.dir" value="${build.dir}/strap"/> <property name="build-docs.dir" value="${build.dir}/scaladoc"/> <property name="build-libs.dir" value="${build.dir}/libs"/> @@ -279,6 +280,28 @@ INITIALISATION <property name="init.maven.tasks.finished" value="true" /> </target> + <target name="init.extra.tasks" depends="init.maven.tasks" unless="init.extra.tasks.finished"> + <artifact:dependencies pathId="extra.tasks.classpath" filesetId="extra.tasks.fileset"> + <dependency groupId="biz.aQute" artifactId="bnd" version="1.50.0"/> + </artifact:dependencies> + <!-- Pax runner --> + <property name="pax.exam.version" value="2.5.0"/> + <artifact:dependencies pathId="pax.exam.classpath" filesetId="pax.exam.fileset"> + <dependency groupId="org.ops4j.pax.exam" artifactId="pax-exam-container-native" version="${pax.exam.version}"/> + <dependency groupId="org.ops4j.pax.exam" artifactId="pax-exam-junit4" version="${pax.exam.version}"/> + <dependency groupId="org.ops4j.pax.exam" artifactId="pax-exam-link-assembly" version="${pax.exam.version}"/> + <dependency groupId="org.ops4j.pax.url" artifactId="pax-url-aether" version="1.4.0"/> + <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="org.apache.felix" artifactId="org.apache.felix.framework" version="3.2.2"/> + </artifact:dependencies> + <!-- BND support --> + <typedef resource="aQute/bnd/ant/taskdef.properties" classpathref="extra.tasks.classpath" /> + <property name="init.maven.tasks.finished" value="true" /> + </target> + <!-- Resolve maven dependencies --> <target name="init.maven.jars" depends="init.maven.tasks"> <!-- This target has an issue where if the user directory does not exist, we BOMB. ugh. --> @@ -400,7 +423,7 @@ INITIALISATION </echo> </target> - <target name="init" depends="init.jars, init.maven.jars, init.version.done, init.fail.bad.jdk, init.warn.jdk7"> + <target name="init" depends="init.jars, init.maven.jars, init.version.done, init.fail.bad.jdk, init.warn.jdk7, init.extra.tasks"> <property name="scalac.args.always" value="-Yreify-copypaste" /> <!-- scalac.args.optimise is selectively overridden in certain antcall tasks. --> <property name="scalac.args.optimise" value=""/> @@ -1673,6 +1696,139 @@ PACKED QUICK BUILD (PACK) </target> <!-- =========================================================================== +OSGi Artifacts +============================================================================ --> + + <target name="osgi.init" depends="pack.done"> + <mkdir dir="${build-osgi.dir}"/> + + <property name="osgi.test.src" value="${partest.dir}/osgi/src"/> + <property name="osgi.test.classes" value="${build-osgi.dir}/classes"/> + + <!-- simplify fixing pom versions --> + <macrodef name="make-bundle"> + <attribute name="name" /> + <attribute name="version" /> + <sequential> + <copy file="${src.dir}/build/bnd/@{name}.bnd" tofile="${build-osgi.dir}/@{name}.bnd" overwrite="true"> + <filterset> + <filter token="VERSION" value="@{version}" /> + </filterset> + </copy> + <bnd classpath="${build-pack.dir}/lib/@{name}.jar" + eclipse="false" + failok="false" + exceptions="true" + files="${build-osgi.dir}/@{name}.bnd" + output="${build-osgi.dir}"/> + </sequential> + </macrodef> + <macrodef name="make-plugin-bundle"> + <attribute name="name" /> + <attribute name="version" /> + <sequential> + <copy file="${src.dir}/build/bnd/@{name}.bnd" tofile="${build-osgi.dir}/@{name}.bnd" overwrite="true"> + <filterset> + <filter token="VERSION" value="@{version}" /> + </filterset> + </copy> + <bnd classpath="${build-pack.dir}/misc/scala-devel/plugins/@{name}.jar" + eclipse="false" + failok="false" + exceptions="true" + files="${build-osgi.dir}/@{name}.bnd" + output="${build-osgi.dir}"/> + </sequential> + </macrodef> + <uptodate property="osgi.bundles.available" targetfile="${build-osgi.dir}/bundles.complete"> + <srcfiles dir="${basedir}"> + <include name="build.xml"/> + <include name="src/build/bnd/*.bnd"/> + </srcfiles> + </uptodate> + </target> + + <target name="osgi.bundles" depends="osgi.init" unless="osgi.bundles.available"> + <stopwatch name="osgi.bundle.timer"/> + <make-bundle name="scala-library" version="${osgi.version.number}" /> + <make-bundle name="scala-actors" version="${osgi.version.number}" /> + <make-bundle name="scala-actors-migration" version="${osgi.version.number}" /> + <make-bundle name="scala-reflect" version="${osgi.version.number}" /> + <make-bundle name="scala-compiler" version="${osgi.version.number}" /> + <make-plugin-bundle name="continuations" version="${osgi.version.number}" /> + <touch file="${build-osgi.dir}/bundles.complete" verbose="no"/> + <stopwatch name="osgi.bundle.timer" action="total"/> + </target> + + <target name="osgi.bundles.swing" depends="osgi.init" if="has.java6" unless="osgi.bundles.available"> + <!-- TODO - only if JDK6 --> + <make-bundle name="scala-swing" version="${osgi.version.number}"/> + </target> + + <target name="osgi.done" depends="osgi.bundles, osgi.bundles.swing"/> + + <target name="osgi.test.init" depends="osgi.done"> + <path id="osgi.bundle.classpath"> + <pathelement location="${build-osgi.dir}/org.scala-lang.scala-library.jar"/> + <pathelement location="${build-osgi.dir}/org.scala-lang.scala-reflect.jar"/> + <pathelement location="${build-osgi.dir}/org.scala-lang.scala-compiler.jar"/> + <pathelement location="${build-osgi.dir}/org.scala-lang.scala-actors.jar"/> + <pathelement location="${build-osgi.dir}/org.scala-lang.scala-actors-migration.jar"/> + </path> + + <uptodate property="osgi.test.available" targetfile="${build-osgi.dir}/test-compile.complete"> + <srcfiles dir="${osgi.test.src}"> + <include name="**/*.scala"/> + </srcfiles> + </uptodate> + </target> + + <target name="osgi.test.comp" depends="osgi.test.init, quick.done" unless="osgi.test.available"> + <stopwatch name="osgi.test.comp.timer"/> + <mkdir dir="${osgi.test.classes}"/> + <scalacfork + destdir="${osgi.test.classes}" + compilerpathref="quick.classpath" + params="${scalac.args.quick}" + srcdir="${osgi.test.src}" + jvmargs="${scalacfork.jvmargs}"> + <include name="**/*.scala"/> + <compilationpath> + <pathelement location="${osgi.test.classes}"/> + <path refid="osgi.bundle.classpath"/> + <path refid="pax.exam.classpath"/> + <path refid="forkjoin.classpath"/> + </compilationpath> + </scalacfork> + <touch file="${build-osgi.dir}/test-compile.complete" verbose="no"/> + <stopwatch name="osgi.test.comp.timer" action="total"/> + </target> + + <target name="osgi.test" depends="osgi.test.comp"> + <stopwatch name="osgi.test.timer"/> + <mkdir dir="${osgi.test.classes}"/> + <junit fork="yes" haltonfailure="yes"> + <classpath> + <pathelement location="${osgi.test.classes}"/> + <path refid="osgi.bundle.classpath"/> + <path refid="pax.exam.classpath"/> + <path refid="forkjoin.classpath"/> + </classpath> + <batchtest fork="yes" todir="${build-osgi.dir}"> + <fileset dir="${osgi.test.classes}"> + <include name="**/*Test.class"/> + </fileset> + </batchtest> + <formatter type="brief" usefile="false" /> + </junit> + <stopwatch name="osgi.test.timer" action="total"/> + </target> + + <target name="osgi.clean"> + <delete dir="${build-osgi.dir}" includeemptydirs="yes" quiet="yes" failonerror="no"/> + </target> + +<!-- =========================================================================== BOOTSTRAPPING BUILD (STRAP) ============================================================================ --> @@ -2553,9 +2709,24 @@ BOOTRAPING TEST AND TEST SUITE DISTRIBUTION ============================================================================ --> - <target name="dist.start" depends="pack.done"> + <target name="dist.start" depends="pack.done, osgi.done"> <property name="dist.name" value="scala-${version.number}"/> <property name="dist.dir" value="${dists.dir}/${dist.name}"/> + + <macrodef name="copy-bundle"> + <attribute name="name" /> + <sequential> + <copy file="${build-osgi.dir}/org.scala-lang.@{name}.jar" + tofile="${dist.dir}/lib/@{name}.jar"/> + </sequential> + </macrodef> + <macrodef name="copy-plugin-bundle"> + <attribute name="name" /> + <sequential> + <copy file="${build-osgi.dir}/org.scala-lang.plugins.@{name}.jar" + tofile="${dist.dir}/misc/scala-devel/plugins/@{name}.jar"/> + </sequential> + </macrodef> </target> <target name="dist.base" depends="dist.start"> @@ -2564,6 +2735,13 @@ DISTRIBUTION <fileset dir="${build-pack.dir}/lib"/> </copy> <mkdir dir="${dist.dir}/bin"/> + <!-- TODO - Stop being inefficient and don't copy OSGi bundles overtop other jars. --> + <copy-bundle name="scala-library"/> + <copy-bundle name="scala-reflect"/> + <copy-bundle name="scala-swing"/> + <copy-bundle name="scala-actors"/> + <copy-bundle name="scala-actors-migration"/> + <copy-bundle name="scala-compiler"/> <copy toDir="${dist.dir}/bin"> <fileset dir="${build-pack.dir}/bin"/> </copy> @@ -2573,9 +2751,7 @@ DISTRIBUTION <chmod perm="ugo+rx" file="${dist.dir}/bin/fsc"/> <chmod perm="ugo+rx" file="${dist.dir}/bin/scalap"/> <mkdir dir="${dist.dir}/misc/scala-devel/plugins"/> - <copy toDir="${dist.dir}/misc/scala-devel/plugins"> - <fileset dir="${build-pack.dir}/misc/scala-devel/plugins"/> - </copy> + <copy-plugin-bundle name="continuations"/> </target> <target name="dist.doc" depends="dist.base, docs.done"> @@ -2663,7 +2839,7 @@ TEST AND DISTRIBUTION BUNDLE (ALL) <target name="all.done" depends="dist.done, test.done"/> - <target name="all.clean" depends="locker.clean, docs.clean, dist.clean, sbt.clean"/> + <target name="all.clean" depends="locker.clean, docs.clean, dist.clean, sbt.clean, osgi.clean"/> <!-- =========================================================================== STABLE REFERENCE (STARR) diff --git a/src/actors-migration/scala/actors/Pattern.scala b/src/actors-migration/scala/actors/Pattern.scala index fa2db79152..a97ee3ba07 100644 --- a/src/actors-migration/scala/actors/Pattern.scala +++ b/src/actors-migration/scala/actors/Pattern.scala @@ -1,6 +1,6 @@ package scala.actors -import scala.concurrent.util.Duration +import scala.concurrent.duration.Duration import scala.language.implicitConversions object pattern { diff --git a/src/actors-migration/scala/actors/StashingActor.scala b/src/actors-migration/scala/actors/StashingActor.scala index 29f370a3e2..775d115d0b 100644 --- a/src/actors-migration/scala/actors/StashingActor.scala +++ b/src/actors-migration/scala/actors/StashingActor.scala @@ -1,7 +1,7 @@ package scala.actors import scala.collection._ -import scala.concurrent.util.Duration +import scala.concurrent.duration.Duration import java.util.concurrent.TimeUnit import scala.language.implicitConversions diff --git a/src/actors-migration/scala/actors/Timeout.scala b/src/actors-migration/scala/actors/Timeout.scala index 5540d2880e..c3017d8569 100644 --- a/src/actors-migration/scala/actors/Timeout.scala +++ b/src/actors-migration/scala/actors/Timeout.scala @@ -8,7 +8,7 @@ package scala.actors -import scala.concurrent.util.Duration +import scala.concurrent.duration.Duration import java.util.concurrent.TimeUnit import scala.language.implicitConversions diff --git a/src/actors/scala/actors/ActorRef.scala b/src/actors/scala/actors/ActorRef.scala index 8f70b13e01..7768f04c2b 100644 --- a/src/actors/scala/actors/ActorRef.scala +++ b/src/actors/scala/actors/ActorRef.scala @@ -1,7 +1,7 @@ package scala.actors import java.util.concurrent.TimeoutException -import scala.concurrent.util.Duration +import scala.concurrent.duration.Duration /** * Trait used for migration of Scala actors to Akka. diff --git a/src/build/bnd/continuations.bnd b/src/build/bnd/continuations.bnd new file mode 100644 index 0000000000..748502f653 --- /dev/null +++ b/src/build/bnd/continuations.bnd @@ -0,0 +1,5 @@ +Bundle-Name: Scala Continuations Plugin +Bundle-SymbolicName: org.scala-lang.plugins.continuations +ver: @VERSION@ +Bundle-Version: ${ver} +Export-Package: *;version=${ver} diff --git a/src/build/bnd/scala-actors-migration.bnd b/src/build/bnd/scala-actors-migration.bnd new file mode 100644 index 0000000000..2cddfb620a --- /dev/null +++ b/src/build/bnd/scala-actors-migration.bnd @@ -0,0 +1,5 @@ +Bundle-Name: Scala Actors Migration +Bundle-SymbolicName: org.scala-lang.scala-actors-migration +ver: @VERSION@ +Bundle-Version: ${ver} +Export-Package: *;version=${ver} diff --git a/src/build/bnd/scala-actors.bnd b/src/build/bnd/scala-actors.bnd new file mode 100644 index 0000000000..8d0555777f --- /dev/null +++ b/src/build/bnd/scala-actors.bnd @@ -0,0 +1,5 @@ +Bundle-Name: Scala Actors +Bundle-SymbolicName: org.scala-lang.scala-actors +ver: @VERSION@ +Bundle-Version: ${ver} +Export-Package: *;version=${ver} diff --git a/src/build/bnd/scala-compiler.bnd b/src/build/bnd/scala-compiler.bnd new file mode 100644 index 0000000000..c289843447 --- /dev/null +++ b/src/build/bnd/scala-compiler.bnd @@ -0,0 +1,8 @@ +Bundle-Name: Scala Compiler +Bundle-SymbolicName: org.scala-lang.scala-compiler +ver: @VERSION@ +Bundle-Version: ${ver} +Export-Package: *;version=${ver} +Import-Package: scala.tools.jline.*;resolution:=optional, \ + org.apache.tools.ant.*;resolution:=optional, \ + * diff --git a/src/build/bnd/scala-library.bnd b/src/build/bnd/scala-library.bnd new file mode 100644 index 0000000000..03aff45672 --- /dev/null +++ b/src/build/bnd/scala-library.bnd @@ -0,0 +1,6 @@ +Bundle-Name: Scala Standard Library +Bundle-SymbolicName: org.scala-lang.scala-library +ver: @VERSION@ +Bundle-Version: ${ver} +Export-Package: *;version=${ver} +Import-Package: sun.misc;resolution:=optional, * diff --git a/src/build/bnd/scala-reflect.bnd b/src/build/bnd/scala-reflect.bnd new file mode 100644 index 0000000000..6cda346d3a --- /dev/null +++ b/src/build/bnd/scala-reflect.bnd @@ -0,0 +1,6 @@ +Bundle-Name: Scala Reflect +Bundle-SymbolicName: org.scala-lang.scala-reflect +ver: @VERSION@ +Bundle-Version: ${ver} +Export-Package: *;version=${ver} +Import-Package: scala.tools.nsc;resolution:=optional, * diff --git a/src/build/bnd/scala-swing.bnd b/src/build/bnd/scala-swing.bnd new file mode 100644 index 0000000000..eeacb9bd3f --- /dev/null +++ b/src/build/bnd/scala-swing.bnd @@ -0,0 +1,5 @@ +Bundle-Name: Scala Swing +Bundle-SymbolicName: org.scala-lang.scala-swing +ver: @VERSION@ +Bundle-Version: ${ver} +Export-Package: *;version=${ver} diff --git a/src/compiler/scala/reflect/macros/runtime/Enclosures.scala b/src/compiler/scala/reflect/macros/runtime/Enclosures.scala index ebde4447d7..b5c988ca83 100644 --- a/src/compiler/scala/reflect/macros/runtime/Enclosures.scala +++ b/src/compiler/scala/reflect/macros/runtime/Enclosures.scala @@ -14,7 +14,7 @@ trait Enclosures { // vals are eager to simplify debugging // after all we wouldn't save that much time by making them lazy val macroApplication: Tree = expandee - val enclosingClass: Tree = site.enclClass.tree + val enclosingClass: Tree = enclTrees collectFirst { case x: ImplDef => x } getOrElse EmptyTree val enclosingImplicits: List[(Type, Tree)] = site.openImplicits val enclosingMacros: List[Context] = this :: universe.analyzer.openMacros // include self val enclosingMethod: Tree = site.enclMethod.tree diff --git a/src/compiler/scala/tools/nsc/io/package.scala b/src/compiler/scala/tools/nsc/io/package.scala index 775ad6bde0..ae83a7728b 100644 --- a/src/compiler/scala/tools/nsc/io/package.scala +++ b/src/compiler/scala/tools/nsc/io/package.scala @@ -11,6 +11,23 @@ import java.util.jar.{ Attributes } import scala.language.implicitConversions package object io { + // Forwarders from scala.reflect.io + type AbstractFile = scala.reflect.io.AbstractFile + val AbstractFile = scala.reflect.io.AbstractFile + type Directory = scala.reflect.io.Directory + val Directory = scala.reflect.io.Directory + type File = scala.reflect.io.File + val File = scala.reflect.io.File + type Path = scala.reflect.io.Path + val Path = scala.reflect.io.Path + type PlainFile = scala.reflect.io.PlainFile + val PlainFile = scala.reflect.io.PlainFile + val Streamable = scala.reflect.io.Streamable + type VirtualDirectory = scala.reflect.io.VirtualDirectory + type VirtualFile = scala.reflect.io.VirtualFile + val ZipArchive = scala.reflect.io.ZipArchive + type ZipArchive = scala.reflect.io.ZipArchive + implicit def postfixOps = scala.language.postfixOps // make all postfix ops in this package compile without warning type JManifest = java.util.jar.Manifest diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala index c72fd3681f..8a9d0e58ec 100644 --- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala +++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala @@ -136,7 +136,9 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { tree match { case Template(_, _, _) => if (currentOwner.isDerivedValueClass) { - checkNonCyclic(currentOwner.pos, Set(), currentOwner) + /* This is currently redundant since value classes may not + wrap over other value classes anyway. + checkNonCyclic(currentOwner.pos, Set(), currentOwner) */ extensionDefs(currentOwner.companionModule) = new mutable.ListBuffer[Tree] currentOwner.primaryConstructor.makeNotPrivate(NoSymbol) super.transform(tree) diff --git a/src/compiler/scala/tools/nsc/typechecker/Tags.scala b/src/compiler/scala/tools/nsc/typechecker/Tags.scala index 0dbeafadbe..d82fbd7c77 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Tags.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Tags.scala @@ -59,11 +59,14 @@ trait Tags { * EmptyTree if `concrete` is true and the result contains unresolved (i.e. not spliced) type parameters and abstract type members. * EmptyTree if `allowMaterialization` is false, and there is no array tag in scope. */ - def resolveTypeTag(pos: Position, pre: Type, tp: Type, concrete: Boolean, allowMaterialization: Boolean = true): Tree = { - val tagSym = if (concrete) TypeTagClass else WeakTypeTagClass - val tagTp = if (pre == NoType) TypeRef(ApiUniverseClass.toTypeConstructor, tagSym, List(tp)) else singleType(pre, pre member tagSym.name) - val taggedTp = appliedType(tagTp, List(tp)) - resolveTag(pos, taggedTp, allowMaterialization) - } + def resolveTypeTag(pos: Position, pre: Type, tp: Type, concrete: Boolean, allowMaterialization: Boolean = true): Tree = + // if someone requests a type tag, but scala-reflect.jar isn't on the library classpath, then bail + if (pre == NoType && ApiUniverseClass == NoSymbol) EmptyTree + else { + val tagSym = if (concrete) TypeTagClass else WeakTypeTagClass + val tagTp = if (pre == NoType) TypeRef(ApiUniverseClass.toTypeConstructor, tagSym, List(tp)) else singleType(pre, pre member tagSym.name) + val taggedTp = appliedType(tagTp, List(tp)) + resolveTag(pos, taggedTp, allowMaterialization) + } } }
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 9b93c7a214..af89af74d0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1405,8 +1405,10 @@ trait Typers extends Modes with Adaptations with Tags { case List(acc) => def isUnderlyingAcc(sym: Symbol) = sym == acc || acc.hasAccessorFlag && sym == acc.accessed - if (acc.accessBoundary(clazz) != rootMirror.RootClass) + if (acc.accessBoundary(clazz) != rootMirror.RootClass) unit.error(acc.pos, "value class needs to have a publicly accessible val parameter") + else if (acc.tpe.typeSymbol.isDerivedValueClass) + unit.error(acc.pos, "value class may not wrap another user-defined value class") for (stat <- body) if (!treeInfo.isAllowedInUniversalTrait(stat) && !isUnderlyingAcc(stat.symbol)) unit.error(stat.pos, @@ -1987,32 +1989,44 @@ trait Typers extends Modes with Adaptations with Tags { * - the self-type of the refinement * - a type member of the refinement * - an abstract type declared outside of the refinement. + * - an instance of a value class + * Furthermore, the result type may not be a value class either */ - def checkMethodStructuralCompatible(meth: Symbol): Unit = { - def fail(msg: String) = unit.error(meth.pos, msg) + def checkMethodStructuralCompatible(ddef: DefDef): Unit = { + val meth = ddef.symbol + def fail(pos: Position, msg: String) = unit.error(pos, msg) val tp: Type = meth.tpe match { case mt @ MethodType(_, _) => mt case NullaryMethodType(restpe) => restpe // TODO_NMT: drop NullaryMethodType from resultType? case PolyType(_, restpe) => restpe case _ => NoType } - def failStruct(what: String) = - fail(s"Parameter type in structural refinement may not refer to $what") - for (paramType <- tp.paramTypes) { + def nthParamPos(n: Int) = ddef.vparamss match { + case xs :: _ if xs.length > n => xs(n).pos + case _ => meth.pos + } + def failStruct(pos: Position, what: String, where: String = "Parameter") = + fail(pos, s"$where type in structural refinement may not refer to $what") + + foreachWithIndex(tp.paramTypes) { (paramType, idx) => val sym = paramType.typeSymbol + def paramPos = nthParamPos(idx) if (sym.isAbstractType) { if (!sym.hasTransOwner(meth.owner)) - failStruct("an abstract type defined outside that refinement") + failStruct(paramPos, "an abstract type defined outside that refinement") else if (!sym.hasTransOwner(meth)) - failStruct("a type member of that refinement") + failStruct(paramPos, "a type member of that refinement") } if (sym.isDerivedValueClass) - failStruct("a user-defined value class") + failStruct(paramPos, "a user-defined value class") if (paramType.isInstanceOf[ThisType] && sym == meth.owner) - failStruct("the type of that refinement (self type)") + failStruct(paramPos, "the type of that refinement (self type)") } + if (tp.resultType.typeSymbol.isDerivedValueClass) + failStruct(ddef.tpt.pos, "a user-defined value class", where = "Result") } + def typedUseCase(useCase: UseCase) { def stringParser(str: String): syntaxAnalyzer.Parser = { val file = new BatchSourceFile(context.unit.source.file, str) { @@ -2129,7 +2143,7 @@ trait Typers extends Modes with Adaptations with Tags { } } if (meth.isStructuralRefinementMember) - checkMethodStructuralCompatible(meth) + checkMethodStructuralCompatible(ddef) if (meth.isImplicit && !meth.isSynthetic) meth.info.paramss match { case List(param) :: _ if !param.isImplicit => diff --git a/src/library/scala/concurrent/Awaitable.scala b/src/library/scala/concurrent/Awaitable.scala index 655115349a..3bd7617bce 100644 --- a/src/library/scala/concurrent/Awaitable.scala +++ b/src/library/scala/concurrent/Awaitable.scala @@ -10,7 +10,7 @@ package scala.concurrent -import scala.concurrent.util.Duration +import scala.concurrent.duration.Duration diff --git a/src/library/scala/concurrent/duration/Deadline.scala b/src/library/scala/concurrent/duration/Deadline.scala new file mode 100644 index 0000000000..50e9a75ff7 --- /dev/null +++ b/src/library/scala/concurrent/duration/Deadline.scala @@ -0,0 +1,81 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2012, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.concurrent.duration + +/** + * This class stores a deadline, as obtained via `Deadline.now` or the + * duration DSL: + * + * {{{ + * import scala.concurrent.duration._ + * 3.seconds.fromNow + * }}} + * + * Its main purpose is to manage repeated attempts to achieve something (like + * awaiting a condition) by offering the methods `hasTimeLeft` and `timeLeft`. All + * durations are measured according to `System.nanoTime` aka wall-time; this + * does not take into account changes to the system clock (such as leap + * seconds). + */ +case class Deadline private (time: FiniteDuration) extends Ordered[Deadline] { + /** + * Return a deadline advanced (i.e. moved into the future) by the given duration. + */ + def +(other: FiniteDuration): Deadline = copy(time = time + other) + /** + * Return a deadline moved backwards (i.e. towards the past) by the given duration. + */ + def -(other: FiniteDuration): Deadline = copy(time = time - other) + /** + * Calculate time difference between this and the other deadline, where the result is directed (i.e. may be negative). + */ + def -(other: Deadline): FiniteDuration = time - other.time + /** + * Calculate time difference between this duration and now; the result is negative if the deadline has passed. + * + * '''''Note that on some systems this operation is costly because it entails a system call.''''' + * Check `System.nanoTime` for your platform. + */ + def timeLeft: FiniteDuration = this - Deadline.now + /** + * Determine whether the deadline still lies in the future at the point where this method is called. + * + * '''''Note that on some systems this operation is costly because it entails a system call.''''' + * Check `System.nanoTime` for your platform. + */ + def hasTimeLeft(): Boolean = !isOverdue() + /** + * Determine whether the deadline lies in the past at the point where this method is called. + * + * '''''Note that on some systems this operation is costly because it entails a system call.''''' + * Check `System.nanoTime` for your platform. + */ + def isOverdue(): Boolean = (time.toNanos - System.nanoTime()) < 0 + /** + * The natural ordering for deadline is determined by the natural order of the underlying (finite) duration. + */ + def compare(other: Deadline) = time compare other.time +} + +object Deadline { + /** + * Construct a deadline due exactly at the point where this method is called. Useful for then + * advancing it to obtain a future deadline, or for sampling the current time exactly once and + * then comparing it to multiple deadlines (using subtraction). + */ + def now: Deadline = Deadline(Duration(System.nanoTime, NANOSECONDS)) + + /** + * The natural ordering for deadline is determined by the natural order of the underlying (finite) duration. + */ + implicit object DeadlineIsOrdered extends Ordering[Deadline] { + def compare(a: Deadline, b: Deadline) = a compare b + } + +} diff --git a/src/library/scala/concurrent/util/Duration.scala b/src/library/scala/concurrent/duration/Duration.scala index 3f8b98831e..79f9b4db86 100644 --- a/src/library/scala/concurrent/util/Duration.scala +++ b/src/library/scala/concurrent/duration/Duration.scala @@ -6,90 +6,12 @@ ** |/ ** \* */ -package scala.concurrent.util +package scala.concurrent.duration -import java.util.concurrent.TimeUnit -import TimeUnit._ import java.lang.{ Double => JDouble, Long => JLong } import scala.language.implicitConversions -/** - * This class stores a deadline, as obtained via `Deadline.now` or the - * duration DSL: - * - * {{{ - * import scala.concurrent.util.duration._ - * 3.seconds.fromNow - * }}} - * - * Its main purpose is to manage repeated attempts to achieve something (like - * awaiting a condition) by offering the methods `hasTimeLeft` and `timeLeft`. All - * durations are measured according to `System.nanoTime` aka wall-time; this - * does not take into account changes to the system clock (such as leap - * seconds). - */ -case class Deadline private (time: FiniteDuration) extends Ordered[Deadline] { - /** - * Return a deadline advanced (i.e. moved into the future) by the given duration. - */ - def +(other: FiniteDuration): Deadline = copy(time = time + other) - /** - * Return a deadline moved backwards (i.e. towards the past) by the given duration. - */ - def -(other: FiniteDuration): Deadline = copy(time = time - other) - /** - * Calculate time difference between this and the other deadline, where the result is directed (i.e. may be negative). - */ - def -(other: Deadline): FiniteDuration = time - other.time - /** - * Calculate time difference between this duration and now; the result is negative if the deadline has passed. - * - * '''''Note that on some systems this operation is costly because it entails a system call.''''' - * Check `System.nanoTime` for your platform. - */ - def timeLeft: FiniteDuration = this - Deadline.now - /** - * Determine whether the deadline still lies in the future at the point where this method is called. - * - * '''''Note that on some systems this operation is costly because it entails a system call.''''' - * Check `System.nanoTime` for your platform. - */ - def hasTimeLeft(): Boolean = !isOverdue() - /** - * Determine whether the deadline lies in the past at the point where this method is called. - * - * '''''Note that on some systems this operation is costly because it entails a system call.''''' - * Check `System.nanoTime` for your platform. - */ - def isOverdue(): Boolean = (time.toNanos - System.nanoTime()) < 0 - /** - * The natural ordering for deadline is determined by the natural order of the underlying (finite) duration. - */ - def compare(other: Deadline) = time compare other.time -} - -object Deadline { - /** - * Construct a deadline due exactly at the point where this method is called. Useful for then - * advancing it to obtain a future deadline, or for sampling the current time exactly once and - * then comparing it to multiple deadlines (using subtraction). - */ - def now: Deadline = Deadline(Duration(System.nanoTime, NANOSECONDS)) - - /** - * The natural ordering for deadline is determined by the natural order of the underlying (finite) duration. - */ - implicit object DeadlineIsOrdered extends Ordering[Deadline] { - def compare(a: Deadline, b: Deadline) = a compare b - } -} - object Duration { - /** - * This implicit conversion allows the use of a Deadline in place of a Duration, which will - * insert the time left until the deadline in its place. - */ - implicit def timeLeft(implicit d: Deadline): Duration = d.timeLeft /** * Construct a Duration from the given length and unit. Observe that nanosecond precision may be lost if @@ -102,11 +24,13 @@ object Duration { * @throws IllegalArgumentException if the length was finite but the resulting duration cannot be expressed as a [[FiniteDuration]] */ def apply(length: Double, unit: TimeUnit): Duration = fromNanos(unit.toNanos(1) * length) + /** * Construct a finite duration from the given length and time unit. The unit given is retained * throughout calculations as long as possible, so that it can be retrieved later. */ def apply(length: Long, unit: TimeUnit): FiniteDuration = new FiniteDuration(length, unit) + /** * Construct a finite duration from the given length and time unit, where the latter is * looked up in a list of string representation. Valid choices are: @@ -117,7 +41,7 @@ object Duration { def apply(length: Long, unit: String): FiniteDuration = new FiniteDuration(length, Duration.timeUnit(unit)) // Double stores 52 bits mantissa, but there is an implied '1' in front, making the limit 2^53 - final val maxPreciseDouble = 9007199254740992d + private[this] final val maxPreciseDouble = 9007199254740992d /** * Parse String into Duration. Format is `"<length><unit>"`, where @@ -161,11 +85,11 @@ object Duration { ) // TimeUnit => standard label - protected[util] val timeUnitName: Map[TimeUnit, String] = + protected[duration] val timeUnitName: Map[TimeUnit, String] = timeUnitLabels.toMap mapValues (s => words(s).last) toMap // Label => TimeUnit - protected[util] val timeUnit: Map[String, TimeUnit] = + protected[duration] val timeUnit: Map[String, TimeUnit] = timeUnitLabels flatMap { case (unit, names) => expandLabels(names) map (_ -> unit) } toMap /** @@ -275,13 +199,13 @@ object Duration { if (factor == 0d || factor.isNaN) Undefined else if (factor < 0d) -this else this - def /(factor: Double): Duration = - if (factor.isNaN || factor.isInfinite) Undefined - else if ((factor compare 0d) < 0) -this + def /(divisor: Double): Duration = + if (divisor.isNaN || divisor.isInfinite) Undefined + else if ((divisor compare 0d) < 0) -this else this - def /(other: Duration): Double = other match { + def /(divisor: Duration): Double = divisor match { case _: Infinite => Double.NaN - case x => Double.PositiveInfinity * (if ((this > Zero) ^ (other >= Zero)) -1 else 1) + case x => Double.PositiveInfinity * (if ((this > Zero) ^ (divisor >= Zero)) -1 else 1) } final def isFinite() = false @@ -380,8 +304,7 @@ object Duration { * <p/> * Examples: * {{{ - * import scala.concurrent.util.Duration - * import java.util.concurrent.TimeUnit + * import scala.concurrent.duration._ * * val duration = Duration(100, MILLISECONDS) * val duration = Duration(100, "millis") @@ -396,7 +319,7 @@ object Duration { * <p/> * Implicits are also provided for Int, Long and Double. Example usage: * {{{ - * import scala.concurrent.util.Duration._ + * import scala.concurrent.duration._ * * val duration = 100 millis * }}} @@ -529,12 +452,12 @@ sealed abstract class Duration extends Serializable with Ordered[Duration] { * * $ovf */ - def /(factor: Double): Duration + def /(divisor: Double): Duration /** * Return the quotient of this and that duration as floating-point number. The semantics are * determined by Double as if calculating the quotient of the nanosecond lengths of both factors. */ - def /(other: Duration): Double + def /(divisor: Duration): Double /** * Negate this duration. The only two values which are mapped to themselves are [[Duration.Zero]] and [[Duration.Undefined]]. */ @@ -561,7 +484,7 @@ sealed abstract class Duration extends Serializable with Ordered[Duration] { * * $ovf */ - def div(factor: Double) = this / factor + def div(divisor: Double) = this / divisor /** * Return the quotient of this and that duration as floating-point number. The semantics are * determined by Double as if calculating the quotient of the nanosecond lengths of both factors. @@ -599,6 +522,7 @@ sealed abstract class Duration extends Serializable with Ordered[Duration] { } object FiniteDuration { + implicit object FiniteDurationIsOrdered extends Ordering[FiniteDuration] { def compare(a: FiniteDuration, b: FiniteDuration) = a compare b } @@ -691,29 +615,77 @@ final class FiniteDuration(val length: Long, val unit: TimeUnit) extends Duratio else if ((factor > 0) ^ (this < Zero)) Inf else MinusInf - def /(factor: Double) = - if (!factor.isInfinite) fromNanos(toNanos / factor) - else if (factor.isNaN) Undefined + def /(divisor: Double) = + if (!divisor.isInfinite) fromNanos(toNanos / divisor) + else if (divisor.isNaN) Undefined else Zero // if this is made a constant, then scalac will elide the conditional and always return +0.0, SI-6331 private[this] def minusZero = -0d - def /(other: Duration): Double = - if (other.isFinite) toNanos.toDouble / other.toNanos - else if (other eq Undefined) Double.NaN - else if ((length < 0) ^ (other > Zero)) 0d + def /(divisor: Duration): Double = + if (divisor.isFinite) toNanos.toDouble / divisor.toNanos + else if (divisor eq Undefined) Double.NaN + else if ((length < 0) ^ (divisor > Zero)) 0d else minusZero - // overridden methods taking FiniteDurations, so that you can calculate while statically staying finite + // overloaded methods taking FiniteDurations, so that you can calculate while statically staying finite def +(other: FiniteDuration) = add(other.length, other.unit) def -(other: FiniteDuration) = add(-other.length, other.unit) def plus(other: FiniteDuration) = this + other def minus(other: FiniteDuration) = this - other - override def div(factor: Double) = this / factor - override def mul(factor: Double) = this * factor def min(other: FiniteDuration) = if (this < other) this else other def max(other: FiniteDuration) = if (this > other) this else other + // overloaded methods taking Long so that you can calculate while statically staying finite + + /** + * Return the quotient of this duration and the given integer factor. + * + * @throws ArithmeticException if the factor is 0 + */ + def /(divisor: Long) = fromNanos(toNanos / divisor) + + /** + * Return the product of this duration and the given integer factor. + * + * @throws IllegalArgumentException if the result would overflow the range of FiniteDuration + */ + def *(factor: Long) = new FiniteDuration(safeMul(length, factor), unit) + + /* + * This method avoids the use of Long division, which saves 95% of the time spent, + * by checking that there are enough leading zeros so that the result has a chance + * to fit into a Long again; the remaining edge cases are caught by using the sign + * of the product for overflow detection. + * + * This method is not general purpose because it disallows the (otherwise legal) + * case of Long.MinValue * 1, but that is okay for use in FiniteDuration, since + * Long.MinValue is not a legal `length` anyway. + */ + private def safeMul(_a: Long, _b: Long): Long = { + val a = math.abs(_a) + val b = math.abs(_b) + import java.lang.Long.{ numberOfLeadingZeros => leading } + if (leading(a) + leading(b) < 64) throw new IllegalArgumentException("multiplication overflow") + val product = a * b + if (product < 0) throw new IllegalArgumentException("multiplication overflow") + if (a == _a ^ b == _b) -product else product + } + + /** + * Return the quotient of this duration and the given integer factor. + * + * @throws ArithmeticException if the factor is 0 + */ + def div(divisor: Long) = this / divisor + + /** + * Return the product of this duration and the given integer factor. + * + * @throws IllegalArgumentException if the result would overflow the range of FiniteDuration + */ + def mul(factor: Long) = this * factor + def unary_- = Duration(-length, unit) final def isFinite() = true @@ -724,78 +696,3 @@ final class FiniteDuration(val length: Long, val unit: TimeUnit) extends Duratio } override def hashCode = toNanos.toInt } - -trait DurationConversions extends Any { - import duration.Classifier - protected def durationIn(unit: TimeUnit): FiniteDuration - - def nanoseconds = durationIn(NANOSECONDS) - def nanos = nanoseconds - def nanosecond = nanoseconds - def nano = nanoseconds - - def microseconds = durationIn(MICROSECONDS) - def micros = microseconds - def microsecond = microseconds - def micro = microseconds - - def milliseconds = durationIn(MILLISECONDS) - def millis = milliseconds - def millisecond = milliseconds - def milli = milliseconds - - def seconds = durationIn(SECONDS) - def second = seconds - - def minutes = durationIn(MINUTES) - def minute = minutes - - def hours = durationIn(HOURS) - def hour = hours - - def days = durationIn(DAYS) - def day = days - - def nanoseconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(nanoseconds) - def nanos[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = nanoseconds(c) - def nanosecond[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = nanoseconds(c) - def nano[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = nanoseconds(c) - - def microseconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(microseconds) - def micros[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = microseconds(c) - def microsecond[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = microseconds(c) - def micro[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = microseconds(c) - - def milliseconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(milliseconds) - def millis[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = milliseconds(c) - def millisecond[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = milliseconds(c) - def milli[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = milliseconds(c) - - def seconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(seconds) - def second[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = seconds(c) - - def minutes[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(minutes) - def minute[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = minutes(c) - - def hours[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(hours) - def hour[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = hours(c) - - def days[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(days) - def day[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = days(c) -} - -final class DurationInt(val n: Int) extends AnyVal with DurationConversions { - override protected def durationIn(unit: TimeUnit): FiniteDuration = Duration(n, unit) -} - -final class DurationLong(val n: Long) extends AnyVal with DurationConversions { - override protected def durationIn(unit: TimeUnit): FiniteDuration = Duration(n, unit) -} - -final class DurationDouble(val d: Double) extends AnyVal with DurationConversions { - override protected def durationIn(unit: TimeUnit): FiniteDuration = - Duration(d, unit) match { - case f: FiniteDuration => f - case _ => throw new IllegalArgumentException("Duration DSL not applicable to " + d) - } -} diff --git a/src/library/scala/concurrent/duration/DurationConversions.scala b/src/library/scala/concurrent/duration/DurationConversions.scala new file mode 100644 index 0000000000..2c7e192a0e --- /dev/null +++ b/src/library/scala/concurrent/duration/DurationConversions.scala @@ -0,0 +1,92 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2012, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.concurrent.duration + +import DurationConversions._ + +// Would be nice to limit the visibility of this trait a little bit, +// but it crashes scalac to do so. +trait DurationConversions extends Any { + protected def durationIn(unit: TimeUnit): FiniteDuration + + def nanoseconds = durationIn(NANOSECONDS) + def nanos = nanoseconds + def nanosecond = nanoseconds + def nano = nanoseconds + + def microseconds = durationIn(MICROSECONDS) + def micros = microseconds + def microsecond = microseconds + def micro = microseconds + + def milliseconds = durationIn(MILLISECONDS) + def millis = milliseconds + def millisecond = milliseconds + def milli = milliseconds + + def seconds = durationIn(SECONDS) + def second = seconds + + def minutes = durationIn(MINUTES) + def minute = minutes + + def hours = durationIn(HOURS) + def hour = hours + + def days = durationIn(DAYS) + def day = days + + def nanoseconds[C](c: C)(implicit ev: Classifier[C]): ev.R = ev.convert(nanoseconds) + def nanos[C](c: C)(implicit ev: Classifier[C]): ev.R = nanoseconds(c) + def nanosecond[C](c: C)(implicit ev: Classifier[C]): ev.R = nanoseconds(c) + def nano[C](c: C)(implicit ev: Classifier[C]): ev.R = nanoseconds(c) + + def microseconds[C](c: C)(implicit ev: Classifier[C]): ev.R = ev.convert(microseconds) + def micros[C](c: C)(implicit ev: Classifier[C]): ev.R = microseconds(c) + def microsecond[C](c: C)(implicit ev: Classifier[C]): ev.R = microseconds(c) + def micro[C](c: C)(implicit ev: Classifier[C]): ev.R = microseconds(c) + + def milliseconds[C](c: C)(implicit ev: Classifier[C]): ev.R = ev.convert(milliseconds) + def millis[C](c: C)(implicit ev: Classifier[C]): ev.R = milliseconds(c) + def millisecond[C](c: C)(implicit ev: Classifier[C]): ev.R = milliseconds(c) + def milli[C](c: C)(implicit ev: Classifier[C]): ev.R = milliseconds(c) + + def seconds[C](c: C)(implicit ev: Classifier[C]): ev.R = ev.convert(seconds) + def second[C](c: C)(implicit ev: Classifier[C]): ev.R = seconds(c) + + def minutes[C](c: C)(implicit ev: Classifier[C]): ev.R = ev.convert(minutes) + def minute[C](c: C)(implicit ev: Classifier[C]): ev.R = minutes(c) + + def hours[C](c: C)(implicit ev: Classifier[C]): ev.R = ev.convert(hours) + def hour[C](c: C)(implicit ev: Classifier[C]): ev.R = hours(c) + + def days[C](c: C)(implicit ev: Classifier[C]): ev.R = ev.convert(days) + def day[C](c: C)(implicit ev: Classifier[C]): ev.R = days(c) +} + +/** + * This object just holds some cogs which make the DSL machine work, not for direct consumption. + */ +object DurationConversions { + trait Classifier[C] { + type R + def convert(d: FiniteDuration): R + } + + implicit object spanConvert extends Classifier[span.type] { + type R = FiniteDuration + def convert(d: FiniteDuration) = d + } + + implicit object fromNowConvert extends Classifier[fromNow.type] { + type R = Deadline + def convert(d: FiniteDuration) = Deadline.now + d + } + +} diff --git a/src/library/scala/concurrent/duration/package.scala b/src/library/scala/concurrent/duration/package.scala new file mode 100644 index 0000000000..2fd735f19e --- /dev/null +++ b/src/library/scala/concurrent/duration/package.scala @@ -0,0 +1,75 @@ +package scala.concurrent + +import scala.language.implicitConversions + +package object duration { + /** + * This object can be used as closing token if you prefer dot-less style but do not want + * to enable language.postfixOps: + * + * {{{ + * import scala.concurrent.duration._ + * + * val duration = 2 seconds span + * }}} + */ + object span + + /** + * This object can be used as closing token for declaring a deadline at some future point + * in time: + * + * {{{ + * import scala.concurrent.duration._ + * + * val deadline = 3 seconds fromNow + * }}} + */ + object fromNow + + type TimeUnit = java.util.concurrent.TimeUnit + final val DAYS = java.util.concurrent.TimeUnit.DAYS + final val HOURS = java.util.concurrent.TimeUnit.HOURS + final val MICROSECONDS = java.util.concurrent.TimeUnit.MICROSECONDS + final val MILLISECONDS = java.util.concurrent.TimeUnit.MILLISECONDS + final val MINUTES = java.util.concurrent.TimeUnit.MINUTES + final val NANOSECONDS = java.util.concurrent.TimeUnit.NANOSECONDS + final val SECONDS = java.util.concurrent.TimeUnit.SECONDS + + implicit def pairIntToDuration(p: (Int, TimeUnit)): Duration = Duration(p._1, p._2) + implicit def pairLongToDuration(p: (Long, TimeUnit)): FiniteDuration = Duration(p._1, p._2) + implicit def durationToPair(d: Duration): (Long, TimeUnit) = (d.length, d.unit) + + implicit final class DurationInt(val n: Int) extends AnyVal with DurationConversions { + override protected def durationIn(unit: TimeUnit): FiniteDuration = Duration(n, unit) + } + + implicit final class DurationLong(val n: Long) extends AnyVal with DurationConversions { + override protected def durationIn(unit: TimeUnit): FiniteDuration = Duration(n, unit) + } + + implicit final class DurationDouble(val d: Double) extends AnyVal with DurationConversions { + override protected def durationIn(unit: TimeUnit): FiniteDuration = + Duration(d, unit) match { + case f: FiniteDuration => f + case _ => throw new IllegalArgumentException("Duration DSL not applicable to " + d) + } + } + + /* + * Avoid reflection based invocation by using non-duck type + */ + implicit final class IntMult(val i: Int) extends AnyVal { + def *(d: Duration) = d * i + def *(d: FiniteDuration) = d * i + } + + implicit final class LongMult(val i: Long) extends AnyVal { + def *(d: Duration) = d * i + def *(d: FiniteDuration) = d * i + } + + implicit final class DoubleMult(val f: Double) extends AnyVal { + def *(d: Duration) = d * f + } +} diff --git a/src/library/scala/concurrent/impl/Promise.scala b/src/library/scala/concurrent/impl/Promise.scala index 9228872f2b..a1a3305db0 100644 --- a/src/library/scala/concurrent/impl/Promise.scala +++ b/src/library/scala/concurrent/impl/Promise.scala @@ -8,16 +8,12 @@ package scala.concurrent.impl - - -import java.util.concurrent.TimeUnit.NANOSECONDS import scala.concurrent.{ ExecutionContext, CanAwait, OnCompleteRunnable, TimeoutException, ExecutionException } -import scala.concurrent.util.{ Duration, Deadline, FiniteDuration } +import scala.concurrent.duration.{ Duration, Deadline, FiniteDuration, NANOSECONDS } import scala.annotation.tailrec import scala.util.control.NonFatal import scala.util.{ Try, Success, Failure } - private[concurrent] trait Promise[T] extends scala.concurrent.Promise[T] with scala.concurrent.Future[T] { def future: this.type = this } @@ -48,7 +44,7 @@ private[concurrent] object Promise { case Failure(t) => resolver(t) case _ => source } - + private def resolver[T](throwable: Throwable): Try[T] = throwable match { case t: scala.runtime.NonLocalReturnControl[_] => Success(t.value.asInstanceOf[T]) case t: scala.util.control.ControlThrowable => Failure(new ExecutionException("Boxed ControlThrowable", t)) @@ -56,12 +52,12 @@ private[concurrent] object Promise { case e: Error => Failure(new ExecutionException("Boxed Error", e)) case t => Failure(t) } - + /** Default promise implementation. */ class DefaultPromise[T] extends AbstractPromise with Promise[T] { self => updateState(null, Nil) // Start at "No callbacks" - + protected final def tryAwait(atMost: Duration): Boolean = { @tailrec def awaitUnsafe(deadline: Deadline, nextWait: FiniteDuration): Boolean = { diff --git a/src/library/scala/concurrent/package.scala b/src/library/scala/concurrent/package.scala index 1d06341d4d..e683732e41 100644 --- a/src/library/scala/concurrent/package.scala +++ b/src/library/scala/concurrent/package.scala @@ -8,7 +8,7 @@ package scala -import scala.concurrent.util.Duration +import scala.concurrent.duration.Duration import scala.annotation.implicitNotFound /** This package object contains primitives for concurrent and parallel programming. diff --git a/src/library/scala/concurrent/util/duration/Classifier.scala b/src/library/scala/concurrent/util/duration/Classifier.scala deleted file mode 100644 index 10faf0a5ce..0000000000 --- a/src/library/scala/concurrent/util/duration/Classifier.scala +++ /dev/null @@ -1,9 +0,0 @@ -package scala.concurrent.util.duration - -import scala.concurrent.util.{ FiniteDuration } - -trait Classifier[C] { - type R - def convert(d: FiniteDuration): R -} - diff --git a/src/library/scala/concurrent/util/duration/IntMult.scala b/src/library/scala/concurrent/util/duration/IntMult.scala deleted file mode 100644 index 94c58fb8c2..0000000000 --- a/src/library/scala/concurrent/util/duration/IntMult.scala +++ /dev/null @@ -1,18 +0,0 @@ -package scala.concurrent.util.duration - -import scala.concurrent.util.{ Duration } - -/* - * Avoid reflection based invocation by using non-duck type - */ -protected[duration] class IntMult(i: Int) { - def *(d: Duration) = d * i -} - -protected[duration] class LongMult(i: Long) { - def *(d: Duration) = d * i -} - -protected[duration] class DoubleMult(f: Double) { - def *(d: Duration) = d * f -} diff --git a/src/library/scala/concurrent/util/duration/package.scala b/src/library/scala/concurrent/util/duration/package.scala deleted file mode 100644 index d5ae3f1544..0000000000 --- a/src/library/scala/concurrent/util/duration/package.scala +++ /dev/null @@ -1,31 +0,0 @@ -package scala.concurrent.util - -import java.util.concurrent.TimeUnit -import scala.language.implicitConversions - -package object duration { - - object span - implicit object spanConvert extends Classifier[span.type] { - type R = FiniteDuration - def convert(d: FiniteDuration) = d - } - - object fromNow - implicit object fromNowConvert extends Classifier[fromNow.type] { - type R = Deadline - def convert(d: FiniteDuration) = Deadline.now + d - } - - implicit def intToDurationInt(n: Int) = new DurationInt(n) - implicit def longToDurationLong(n: Long) = new DurationLong(n) - implicit def doubleToDurationDouble(d: Double) = new DurationDouble(d) - - implicit def pairIntToDuration(p: (Int, TimeUnit)) = Duration(p._1, p._2) - implicit def pairLongToDuration(p: (Long, TimeUnit)) = Duration(p._1, p._2) - implicit def durationToPair(d: Duration) = (d.length, d.unit) - - implicit def intMult(i: Int) = new IntMult(i) - implicit def longMult(l: Long) = new LongMult(l) - implicit def doubleMult(f: Double) = new DoubleMult(f) -} diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala index 542673ff00..78345e27f2 100644 --- a/src/reflect/scala/reflect/api/Symbols.scala +++ b/src/reflect/scala/reflect/api/Symbols.scala @@ -210,7 +210,7 @@ trait Symbols { self: Universe => /** Source file if this symbol is created during this compilation run, * or a class file if this symbol is loaded from a *.class or *.jar. */ - def associatedFile: scala.tools.nsc.io.AbstractFile + def associatedFile: scala.reflect.io.AbstractFile /** A list of annotations attached to this Symbol. */ diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 50e5afd21e..a0e28bf735 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -11,7 +11,7 @@ import scala.collection.mutable.ListBuffer import util.Statistics import Flags._ import scala.annotation.tailrec -import scala.tools.nsc.io.AbstractFile +import scala.reflect.io.AbstractFile trait Symbols extends api.Symbols { self: SymbolTable => import definitions._ diff --git a/src/reflect/scala/reflect/internal/util/SourceFile.scala b/src/reflect/scala/reflect/internal/util/SourceFile.scala index 9a71e02e08..788c7532d1 100644 --- a/src/reflect/scala/reflect/internal/util/SourceFile.scala +++ b/src/reflect/scala/reflect/internal/util/SourceFile.scala @@ -6,7 +6,7 @@ package scala.reflect.internal.util -import scala.tools.nsc.io.{ AbstractFile, VirtualFile } +import scala.reflect.io.{ AbstractFile, VirtualFile } import scala.collection.mutable.ArrayBuffer import scala.annotation.tailrec import java.util.regex.Pattern diff --git a/src/reflect/scala/tools/nsc/io/AbstractFile.scala b/src/reflect/scala/reflect/io/AbstractFile.scala index 018a017c6d..e32207c58c 100644 --- a/src/reflect/scala/tools/nsc/io/AbstractFile.scala +++ b/src/reflect/scala/reflect/io/AbstractFile.scala @@ -4,7 +4,7 @@ */ -package scala.tools.nsc +package scala.reflect package io import java.io.{ FileOutputStream, IOException, InputStream, OutputStream, BufferedOutputStream } @@ -13,6 +13,10 @@ import java.net.URL import scala.collection.mutable.ArrayBuffer /** + * An abstraction over files for use in the reflection/compiler libraries. + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' + * * @author Philippe Altherr * @version 1.0, 23/03/2004 */ @@ -81,6 +85,8 @@ object AbstractFile { * all other cases, the class <code>SourceFile</code> is used, which honors * <code>global.settings.encoding.value</code>. * </p> + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ abstract class AbstractFile extends Iterable[AbstractFile] { diff --git a/src/reflect/scala/tools/nsc/io/Directory.scala b/src/reflect/scala/reflect/io/Directory.scala index ebd6edc8d8..a24534137d 100644 --- a/src/reflect/scala/tools/nsc/io/Directory.scala +++ b/src/reflect/scala/reflect/io/Directory.scala @@ -6,11 +6,13 @@ ** |/ ** \* */ -package scala.tools.nsc +package scala.reflect package io import java.io.{ File => JFile } - +/** + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' + */ object Directory { import scala.util.Properties.{ tmpDir, userHome, userDir } @@ -34,6 +36,8 @@ import Path._ * * @author Paul Phillips * @since 2.8 + * + * ''Note: This is library is considered experimental and should not be used unless you know what you are doing.'' */ class Directory(jfile: JFile) extends Path(jfile) { override def toAbsolute: Directory = if (isAbsolute) this else super.toAbsolute.toDirectory diff --git a/src/reflect/scala/tools/nsc/io/File.scala b/src/reflect/scala/reflect/io/File.scala index fce0e339e0..9e306371f7 100644 --- a/src/reflect/scala/tools/nsc/io/File.scala +++ b/src/reflect/scala/reflect/io/File.scala @@ -7,7 +7,7 @@ \* */ -package scala.tools.nsc +package scala.reflect package io import java.io.{ @@ -17,7 +17,9 @@ import java.io.{ File => JFile } import java.nio.channels.{ Channel, FileChannel } import scala.io.Codec import scala.language.{reflectiveCalls, implicitConversions} - +/** + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' + */ object File { def pathSeparator = java.io.File.pathSeparator def separator = java.io.File.separator @@ -74,6 +76,8 @@ import Path._ * * @author Paul Phillips * @since 2.8 + * + * ''Note: This is library is considered experimental and should not be used unless you know what you are doing.'' */ class File(jfile: JFile)(implicit constructorCodec: Codec) extends Path(jfile) with Streamable.Chars { override val creationCodec = constructorCodec diff --git a/src/reflect/scala/tools/nsc/io/FileOperationException.scala b/src/reflect/scala/reflect/io/FileOperationException.scala index f23658efbc..6bce799cea 100644 --- a/src/reflect/scala/tools/nsc/io/FileOperationException.scala +++ b/src/reflect/scala/reflect/io/FileOperationException.scala @@ -7,7 +7,7 @@ \* */ -package scala.tools.nsc +package scala.reflect package io - +/** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ case class FileOperationException(msg: String) extends RuntimeException(msg) diff --git a/src/reflect/scala/tools/nsc/io/NoAbstractFile.scala b/src/reflect/scala/reflect/io/NoAbstractFile.scala index 2af933c27b..d503328a37 100644 --- a/src/reflect/scala/tools/nsc/io/NoAbstractFile.scala +++ b/src/reflect/scala/reflect/io/NoAbstractFile.scala @@ -3,7 +3,7 @@ * @author Paul Phillips */ -package scala.tools.nsc +package scala.reflect package io import java.io.InputStream @@ -11,6 +11,8 @@ import java.io.{ File => JFile } /** A distinguished object so you can avoid both null * and Option. + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ object NoAbstractFile extends AbstractFile { def absolute: AbstractFile = this diff --git a/src/reflect/scala/tools/nsc/io/Path.scala b/src/reflect/scala/reflect/io/Path.scala index 0a27e49686..9a1ff395a3 100644 --- a/src/reflect/scala/tools/nsc/io/Path.scala +++ b/src/reflect/scala/reflect/io/Path.scala @@ -3,7 +3,7 @@ * @author Paul Phillips */ -package scala.tools.nsc +package scala.reflect package io import java.io.{ @@ -27,8 +27,9 @@ import scala.language.implicitConversions * * @author Paul Phillips * @since 2.8 + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ - object Path { def isExtensionJarOrZip(jfile: JFile): Boolean = isExtensionJarOrZip(jfile.getName) def isExtensionJarOrZip(name: String): Boolean = { @@ -83,6 +84,8 @@ import Path._ /** The Path constructor is private so we can enforce some * semantics regarding how a Path might relate to the world. + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ class Path private[io] (val jfile: JFile) { val separator = java.io.File.separatorChar diff --git a/src/reflect/scala/tools/nsc/io/PlainFile.scala b/src/reflect/scala/reflect/io/PlainFile.scala index a4f378ad5e..14cb09317c 100644 --- a/src/reflect/scala/tools/nsc/io/PlainFile.scala +++ b/src/reflect/scala/reflect/io/PlainFile.scala @@ -4,12 +4,12 @@ */ -package scala.tools.nsc +package scala.reflect package io import java.io.{ FileInputStream, FileOutputStream, IOException } import PartialFunction._ - +/** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ object PlainFile { /** * If the specified File exists, returns an abstract file backed @@ -20,7 +20,7 @@ object PlainFile { else if (file.isFile) new PlainFile(file) else null } - +/** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ class PlainDirectory(givenPath: Directory) extends PlainFile(givenPath) { override def isDirectory = true override def iterator = givenPath.list filter (_.exists) map (x => new PlainFile(x)) @@ -28,6 +28,8 @@ class PlainDirectory(givenPath: Directory) extends PlainFile(givenPath) { } /** This class implements an abstract file backed by a File. + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ class PlainFile(val givenPath: Path) extends AbstractFile { assert(path ne null) diff --git a/src/reflect/scala/tools/nsc/io/Streamable.scala b/src/reflect/scala/reflect/io/Streamable.scala index 625429bdb3..a083890e09 100644 --- a/src/reflect/scala/tools/nsc/io/Streamable.scala +++ b/src/reflect/scala/reflect/io/Streamable.scala @@ -3,7 +3,7 @@ * @author Paul Phillips */ -package scala.tools.nsc +package scala.reflect package io import java.net.{ URI, URL } @@ -17,12 +17,15 @@ import Path.fail * * @author Paul Phillips * @since 2.8 + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ - object Streamable { /** Traits which can be viewed as a sequence of bytes. Source types * which know their length should override def length: Long for more * efficient method implementations. + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ trait Bytes { def inputStream(): InputStream @@ -66,6 +69,8 @@ object Streamable { } /** For objects which can be viewed as Chars. + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ trait Chars extends Bytes { /** Calls to methods requiring byte<->char transformations should be offered diff --git a/src/reflect/scala/tools/nsc/io/VirtualDirectory.scala b/src/reflect/scala/reflect/io/VirtualDirectory.scala index fa016f86f4..e71c5cbb6b 100644 --- a/src/reflect/scala/tools/nsc/io/VirtualDirectory.scala +++ b/src/reflect/scala/reflect/io/VirtualDirectory.scala @@ -2,7 +2,7 @@ * Copyright 2005-2012 LAMP/EPFL */ -package scala.tools.nsc +package scala.reflect package io import scala.collection.mutable @@ -11,6 +11,8 @@ import scala.collection.mutable * An in-memory directory. * * @author Lex Spoon + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ class VirtualDirectory(val name: String, maybeContainer: Option[VirtualDirectory]) extends AbstractFile { diff --git a/src/reflect/scala/tools/nsc/io/VirtualFile.scala b/src/reflect/scala/reflect/io/VirtualFile.scala index 8a5114bfe7..4884561f4e 100644 --- a/src/reflect/scala/tools/nsc/io/VirtualFile.scala +++ b/src/reflect/scala/reflect/io/VirtualFile.scala @@ -4,7 +4,7 @@ */ -package scala.tools.nsc +package scala.reflect package io import java.io.{ ByteArrayInputStream, ByteArrayOutputStream, InputStream, OutputStream } @@ -14,6 +14,8 @@ import java.io.{ File => JFile } * * @author Philippe Altherr * @version 1.0, 23/03/2004 + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ class VirtualFile(val name: String, override val path: String) extends AbstractFile { /** diff --git a/src/reflect/scala/tools/nsc/io/ZipArchive.scala b/src/reflect/scala/reflect/io/ZipArchive.scala index 49d2200895..2512c4d92f 100644 --- a/src/reflect/scala/tools/nsc/io/ZipArchive.scala +++ b/src/reflect/scala/reflect/io/ZipArchive.scala @@ -3,7 +3,7 @@ * @author Paul Phillips */ -package scala.tools.nsc +package scala.reflect package io import java.net.URL @@ -20,6 +20,8 @@ import scala.annotation.tailrec * @author Philippe Altherr (original version) * @author Paul Phillips (this one) * @version 2.0, + * + * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ object ZipArchive { def fromPath(path: String): FileZipArchive = fromFile(new JFile(path)) @@ -57,7 +59,7 @@ object ZipArchive { } } import ZipArchive._ - +/** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ abstract class ZipArchive(override val file: JFile) extends AbstractFile with Equals { self => @@ -78,13 +80,14 @@ abstract class ZipArchive(override val file: JFile) extends AbstractFile with Eq } } def deepIterator = walkIterator(iterator) - + /** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ sealed abstract class Entry(path: String) extends VirtualFile(baseName(path), path) { // have to keep this name for compat with sbt's compiler-interface def getArchive: ZipFile = null override def underlyingSource = Some(self) override def toString = self.path + "(" + path + ")" } + /** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ class DirEntry(path: String) extends Entry(path) { val entries = mutable.HashMap[String, Entry]() @@ -120,7 +123,7 @@ abstract class ZipArchive(override val file: JFile) extends AbstractFile with Eq else ensureDir(dirs, dirName(entry.getName), null) } } - +/** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ final class FileZipArchive(file: JFile) extends ZipArchive(file) { def iterator: Iterator[Entry] = { val zipFile = new ZipFile(file) @@ -161,7 +164,7 @@ final class FileZipArchive(file: JFile) extends ZipArchive(file) { case _ => false } } - +/** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ final class URLZipArchive(val url: URL) extends ZipArchive(null) { def iterator: Iterator[Entry] = { val root = new DirEntry("/") diff --git a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala index eaf7d8326f..44d9d94a46 100644 --- a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala +++ b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala @@ -49,7 +49,7 @@ object ReflectionUtils { case cl: java.net.URLClassLoader => (cl.getURLs mkString ",") case cl if cl != null && isAbstractFileClassLoader(cl.getClass) => - cl.asInstanceOf[{val root: scala.tools.nsc.io.AbstractFile}].root.canonicalPath + cl.asInstanceOf[{val root: scala.reflect.io.AbstractFile}].root.canonicalPath case null => inferBootClasspath case _ => diff --git a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala index 7705610efb..3c2885a9f4 100644 --- a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala +++ b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala @@ -1,7 +1,7 @@ package scala.reflect package runtime -import scala.tools.nsc.io.AbstractFile +import scala.reflect.io.AbstractFile trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable => diff --git a/test/files/jvm/actmig-PinS.scala b/test/files/jvm/actmig-PinS.scala index 39f8f04b3b..30307f3737 100644 --- a/test/files/jvm/actmig-PinS.scala +++ b/test/files/jvm/actmig-PinS.scala @@ -1,5 +1,5 @@ import scala.actors._ -import scala.concurrent.util.duration._ +import scala.concurrent.duration._ import scala.concurrent.{ Promise, Await } import scala.actors.Actor._ diff --git a/test/files/jvm/actmig-PinS_1.scala b/test/files/jvm/actmig-PinS_1.scala index 1fb50567b9..640684f728 100644 --- a/test/files/jvm/actmig-PinS_1.scala +++ b/test/files/jvm/actmig-PinS_1.scala @@ -1,5 +1,5 @@ import scala.actors._ -import scala.concurrent.util.duration._ +import scala.concurrent.duration._ import scala.concurrent.{ Promise, Await } object SillyActor { diff --git a/test/files/jvm/actmig-PinS_2.scala b/test/files/jvm/actmig-PinS_2.scala index 46277efd43..761df6b5a7 100644 --- a/test/files/jvm/actmig-PinS_2.scala +++ b/test/files/jvm/actmig-PinS_2.scala @@ -1,5 +1,5 @@ import scala.actors.{ MigrationSystem, StashingActor, ActorRef, Props, Exit } -import scala.concurrent.util.duration._ +import scala.concurrent.duration._ import scala.concurrent.{ Promise, Await } object SillyActor { diff --git a/test/files/jvm/actmig-PinS_3.scala b/test/files/jvm/actmig-PinS_3.scala index 321e99b1c2..de9788724d 100644 --- a/test/files/jvm/actmig-PinS_3.scala +++ b/test/files/jvm/actmig-PinS_3.scala @@ -1,5 +1,5 @@ import scala.actors.{ MigrationSystem, StashingActor, ActorRef, Terminated, Props } -import scala.concurrent.util.duration._ +import scala.concurrent.duration._ import scala.concurrent.{ Promise, Await } diff --git a/test/files/jvm/actmig-public-methods_1.scala b/test/files/jvm/actmig-public-methods_1.scala index 7e5bc24210..4bbdc9a71f 100644 --- a/test/files/jvm/actmig-public-methods_1.scala +++ b/test/files/jvm/actmig-public-methods_1.scala @@ -3,7 +3,7 @@ import scala.actors.Actor._ import scala.actors._ import scala.util._ import java.util.concurrent.{ TimeUnit, CountDownLatch } -import scala.concurrent.util.Duration +import scala.concurrent.duration.Duration import scala.actors.pattern._ object Test { diff --git a/test/files/jvm/actmig-react-receive.scala b/test/files/jvm/actmig-react-receive.scala index 8464a2af79..280582511f 100644 --- a/test/files/jvm/actmig-react-receive.scala +++ b/test/files/jvm/actmig-react-receive.scala @@ -3,7 +3,7 @@ import scala.actors.Actor._ import scala.actors.{ Actor, StashingActor, ActorRef, Props, MigrationSystem, PoisonPill } import java.util.concurrent.{ TimeUnit, CountDownLatch } import scala.collection.mutable.ArrayBuffer -import scala.concurrent.util.duration._ +import scala.concurrent.duration._ import scala.concurrent.{ Promise, Await } object Test { diff --git a/test/files/jvm/duration-java/Test.java b/test/files/jvm/duration-java/Test.java index 1c53ccb266..94f3f83db8 100644 --- a/test/files/jvm/duration-java/Test.java +++ b/test/files/jvm/duration-java/Test.java @@ -1,4 +1,4 @@ -import scala.concurrent.util.Duration; +import scala.concurrent.duration.Duration; import java.util.*; import java.util.concurrent.TimeUnit; import static java.util.concurrent.TimeUnit.*; diff --git a/test/files/jvm/duration-tck.scala b/test/files/jvm/duration-tck.scala index 0947e84004..df1052fed3 100644 --- a/test/files/jvm/duration-tck.scala +++ b/test/files/jvm/duration-tck.scala @@ -1,11 +1,9 @@ /** * Copyright (C) 2012 Typesafe Inc. <http://www.typesafe.com> */ - -import scala.concurrent.util._ -import duration._ + +import scala.concurrent.duration._ import scala.reflect._ -import java.util.concurrent.TimeUnit._ import scala.tools.partest.TestUtil.intercept object Test extends App { @@ -39,7 +37,7 @@ object Test extends App { two / one mustBe 2 one + zero mustBe one one / 1000000 mustBe 1.micro - + // test infinities @@ -91,7 +89,7 @@ object Test extends App { minf.toUnit(MINUTES) mustBe Double.NegativeInfinity Duration.fromNanos(Double.PositiveInfinity) mustBe inf Duration.fromNanos(Double.NegativeInfinity) mustBe minf - + // test undefined & NaN @@ -122,7 +120,7 @@ object Test extends App { undef.toUnit(DAYS) mustBe nan Duration.fromNanos(nan) mustBe undef - + // test overflow protection for (unit ← Seq(DAYS, HOURS, MINUTES, SECONDS, MILLISECONDS, MICROSECONDS, NANOSECONDS)) { @@ -153,21 +151,21 @@ object Test extends App { } intercept[IllegalArgumentException] { Duration.fromNanos(1e20) } intercept[IllegalArgumentException] { Duration.fromNanos(-1e20) } - + // test precision 1.second + 1.millisecond mustBe 1001.milliseconds 100000.days + 1.nanosecond mustBe 8640000000000000001L.nanoseconds 1.5.seconds.toSeconds mustBe 1 (-1.5).seconds.toSeconds mustBe -1 - + // test unit stability 1000.millis.unit mustBe MILLISECONDS (1000.millis + 0.days).unit mustBe MILLISECONDS 1.second.unit mustBe SECONDS (1.second + 1.millisecond).unit mustBe MILLISECONDS - + // test Deadline val dead = 2.seconds.fromNow @@ -177,10 +175,20 @@ object Test extends App { Thread.sleep(1.second.toMillis) assert(dead.timeLeft < 1.second) assert(dead2.timeLeft < 1.second) - + + + // test integer mul/div + 500.millis * 2 mustBe 1.second + (500.millis * 2).unit mustBe MILLISECONDS + 1.second / 2 mustBe 500.millis + (1.second / 2).unit mustBe MILLISECONDS + // check statically retaining finite-ness - val finiteDuration: FiniteDuration = 1.second plus 3.seconds minus 1.millisecond min 1.second max 1.second - + val finiteDuration: FiniteDuration = 1.second * 2 / 3 mul 5 div 4 plus 3.seconds minus 1.millisecond min 1.second max 1.second + val finite2: FiniteDuration = 2 * 1.second + 3L * 2.seconds + finite2 mustBe 8.seconds + ((2 seconds fromNow).timeLeft: FiniteDuration) < 4.seconds mustBe true + val finite3: FiniteDuration = 3.5 seconds span } diff --git a/test/files/jvm/future-spec/FutureTests.scala b/test/files/jvm/future-spec/FutureTests.scala index 31bb8c4e44..8674be168c 100644 --- a/test/files/jvm/future-spec/FutureTests.scala +++ b/test/files/jvm/future-spec/FutureTests.scala @@ -2,8 +2,8 @@ import scala.concurrent._ -import scala.concurrent.util.duration._ -import scala.concurrent.util.Duration.Inf +import scala.concurrent.duration._ +import scala.concurrent.duration.Duration.Inf import scala.collection._ import scala.runtime.NonLocalReturnControl import scala.util.{Try,Success,Failure} diff --git a/test/files/jvm/future-spec/PromiseTests.scala b/test/files/jvm/future-spec/PromiseTests.scala index d9aaa1d5ed..8e07393900 100644 --- a/test/files/jvm/future-spec/PromiseTests.scala +++ b/test/files/jvm/future-spec/PromiseTests.scala @@ -2,8 +2,8 @@ import scala.concurrent._ -import scala.concurrent.util.duration._ -import scala.concurrent.util.Duration.Inf +import scala.concurrent.duration._ +import scala.concurrent.duration.Duration.Inf import scala.collection._ import scala.runtime.NonLocalReturnControl import scala.util.{Try,Success,Failure} diff --git a/test/files/jvm/future-spec/main.scala b/test/files/jvm/future-spec/main.scala index 57183d8cea..90048ccda0 100644 --- a/test/files/jvm/future-spec/main.scala +++ b/test/files/jvm/future-spec/main.scala @@ -3,7 +3,7 @@ import scala.collection._ import scala.concurrent._ -import scala.concurrent.util.Duration +import scala.concurrent.duration.Duration import java.util.concurrent.{ TimeoutException, CountDownLatch, TimeUnit } diff --git a/test/files/jvm/scala-concurrent-tck.scala b/test/files/jvm/scala-concurrent-tck.scala index 0e76b711de..b529bca38a 100644 --- a/test/files/jvm/scala-concurrent-tck.scala +++ b/test/files/jvm/scala-concurrent-tck.scala @@ -10,7 +10,7 @@ import scala.concurrent.{ } import scala.concurrent.{ future, promise, blocking } import scala.util.{ Try, Success, Failure } -import scala.concurrent.util.Duration +import scala.concurrent.duration.Duration import scala.reflect.{ classTag, ClassTag } import scala.tools.partest.TestUtil.intercept diff --git a/test/files/neg/deadline-inf-illegal.check b/test/files/neg/deadline-inf-illegal.check index 2b9b25e48e..530d2b2443 100644 --- a/test/files/neg/deadline-inf-illegal.check +++ b/test/files/neg/deadline-inf-illegal.check @@ -1,15 +1,15 @@ -deadline-inf-illegal.scala:5: error: value fromNow is not a member of scala.concurrent.util.Duration +deadline-inf-illegal.scala:5: error: value fromNow is not a member of scala.concurrent.duration.Duration d.fromNow ^ deadline-inf-illegal.scala:6: error: type mismatch; - found : scala.concurrent.util.Duration - required: scala.concurrent.util.FiniteDuration + found : scala.concurrent.duration.Duration + required: scala.concurrent.duration.FiniteDuration Deadline.now + d ^ deadline-inf-illegal.scala:7: error: overloaded method value - with alternatives: - (other: scala.concurrent.util.Deadline)scala.concurrent.util.FiniteDuration <and> - (other: scala.concurrent.util.FiniteDuration)scala.concurrent.util.Deadline - cannot be applied to (scala.concurrent.util.Duration) + (other: scala.concurrent.duration.Deadline)scala.concurrent.duration.FiniteDuration <and> + (other: scala.concurrent.duration.FiniteDuration)scala.concurrent.duration.Deadline + cannot be applied to (scala.concurrent.duration.Duration) Deadline.now - d ^ three errors found diff --git a/test/files/neg/deadline-inf-illegal.scala b/test/files/neg/deadline-inf-illegal.scala index 161089bfee..942cea7014 100644 --- a/test/files/neg/deadline-inf-illegal.scala +++ b/test/files/neg/deadline-inf-illegal.scala @@ -1,4 +1,4 @@ -import concurrent.util.{ Deadline, Duration } +import concurrent.duration.{ Deadline, Duration } class T { val d: Duration = Duration.Zero diff --git a/test/files/neg/structural.check b/test/files/neg/structural.check index 6ef57db1b4..5b2f352a76 100644 --- a/test/files/neg/structural.check +++ b/test/files/neg/structural.check @@ -1,28 +1,28 @@ structural.scala:47: error: Parameter type in structural refinement may not refer to the type of that refinement (self type) val s1 = new { def f(p: this.type): Unit = () } - ^ + ^ structural.scala:10: error: Parameter type in structural refinement may not refer to an abstract type defined outside that refinement def f1[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: A): Object; val x: A }) = x.m[Tata](x.x) //fail - ^ + ^ structural.scala:11: error: Parameter type in structural refinement may not refer to an abstract type defined outside that refinement def f2[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: B): Object; val x: B }) = x.m[Tata](x.x) //fail - ^ + ^ structural.scala:12: error: Parameter type in structural refinement may not refer to an abstract type defined outside that refinement def f3[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: C): Object; val x: C }) = x.m[Tata](x.x) //fail - ^ + ^ structural.scala:13: error: Parameter type in structural refinement may not refer to a type member of that refinement def f4[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: D): Object; val x: D }) = x.m[Tata](x.x) //fail - ^ + ^ structural.scala:42: error: Parameter type in structural refinement may not refer to an abstract type defined outside that refinement type Summable[T] = { def +(v : T) : T } - ^ + ^ structural.scala:46: error: Parameter type in structural refinement may not refer to the type of that refinement (self type) type S1 = { def f(p: this.type): Unit } - ^ + ^ structural.scala:49: error: Parameter type in structural refinement may not refer to a type member of that refinement type S2 = { type T; def f(p: T): Unit } - ^ + ^ structural.scala:52: error: Parameter type in structural refinement may not refer to an abstract type defined outside that refinement def s3[U >: Null <: Object](p: { def f(p: U): Unit; def u: U }) = () - ^ + ^ 9 errors found diff --git a/test/files/neg/t0565.check b/test/files/neg/t0565.check index c5a64d0e53..98e61a2503 100644 --- a/test/files/neg/t0565.check +++ b/test/files/neg/t0565.check @@ -1,4 +1,4 @@ t0565.scala:8: error: Parameter type in structural refinement may not refer to a type member of that refinement def z (w : T) : T } = - ^ + ^ one error found diff --git a/test/files/neg/t2144.check b/test/files/neg/t2144.check index 7239f4406e..670e188c2a 100644 --- a/test/files/neg/t2144.check +++ b/test/files/neg/t2144.check @@ -1,4 +1,4 @@ t2144.scala:2: error: Parameter type in structural refinement may not refer to an abstract type defined outside that refinement def foo[A](a: A) = new { def bar(x: A): A = x } - ^ + ^ one error found diff --git a/test/files/neg/t5878.check b/test/files/neg/t5878.check index 50dba0d272..c60c4653a2 100644 --- a/test/files/neg/t5878.check +++ b/test/files/neg/t5878.check @@ -1,13 +1,13 @@ -t5878.scala:1: error: value class may not unbox to itself +t5878.scala:1: error: value class may not wrap another user-defined value class case class Foo(x: Bar) extends AnyVal - ^ -t5878.scala:2: error: value class may not unbox to itself + ^ +t5878.scala:2: error: value class may not wrap another user-defined value class case class Bar(x: Foo) extends AnyVal - ^ -t5878.scala:4: error: value class may not unbox to itself + ^ +t5878.scala:4: error: value class may not wrap another user-defined value class class Foo1(val x: Bar1) extends AnyVal - ^ -t5878.scala:5: error: value class may not unbox to itself + ^ +t5878.scala:5: error: value class may not wrap another user-defined value class class Bar1(val x: Foo1) extends AnyVal - ^ + ^ four errors found diff --git a/test/files/neg/t6336.check b/test/files/neg/t6336.check index f6b35ad232..f70a5f70ab 100644 --- a/test/files/neg/t6336.check +++ b/test/files/neg/t6336.check @@ -1,4 +1,7 @@ t6336.scala:3: error: Parameter type in structural refinement may not refer to a user-defined value class val a = new { def y[T](x: X[T]) = x.i } - ^ -one error found + ^ +t6336.scala:4: error: Result type in structural refinement may not refer to a user-defined value class + val b = new { def y[T](x: T): X[T] = new X(2) } + ^ +two errors found diff --git a/test/files/neg/t6336.scala b/test/files/neg/t6336.scala index a9844ff94f..b1d61f4dd2 100644 --- a/test/files/neg/t6336.scala +++ b/test/files/neg/t6336.scala @@ -1,6 +1,7 @@ object D { def main(args: Array[String]) { val a = new { def y[T](x: X[T]) = x.i } + val b = new { def y[T](x: T): X[T] = new X(2) } val x = new X(3) val t = a.y(x) println(t) diff --git a/test/files/neg/t6337.check b/test/files/neg/t6337.check new file mode 100644 index 0000000000..8448f71320 --- /dev/null +++ b/test/files/neg/t6337.check @@ -0,0 +1,7 @@ +t6337.scala:10: error: value class may not wrap another user-defined value class +class X[T](val i: XX[T]) extends AnyVal + ^ +t6337.scala:20: error: value class may not wrap another user-defined value class +class X1[T](val i: XX1[T]) extends AnyVal + ^ +two errors found diff --git a/test/files/neg/t6337.scala b/test/files/neg/t6337.scala new file mode 100644 index 0000000000..c3858f8c04 --- /dev/null +++ b/test/files/neg/t6337.scala @@ -0,0 +1,21 @@ +object C { + + def main(args: Array[String]) = { + val x = new X(new XX(3)) + println(x.i.x + 9) + } + +} + +class X[T](val i: XX[T]) extends AnyVal +class XX[T](val x: T) extends AnyVal + +object C1 { + def main(args: Array[String]) { + val x = new X1(new XX1(Some(3))) + println(x.i.x.get + 9) + } +} + +class X1[T](val i: XX1[T]) extends AnyVal +class XX1[T](val x: Option[T]) extends AnyVal diff --git a/test/files/run/t6394a.check b/test/files/run/t6394a.check new file mode 100644 index 0000000000..34997f71e3 --- /dev/null +++ b/test/files/run/t6394a.check @@ -0,0 +1 @@ +TEST
diff --git a/test/files/run/t6394a.flags b/test/files/run/t6394a.flags new file mode 100644 index 0000000000..cd66464f2f --- /dev/null +++ b/test/files/run/t6394a.flags @@ -0,0 +1 @@ +-language:experimental.macros
\ No newline at end of file diff --git a/test/files/run/t6394a/Macros_1.scala b/test/files/run/t6394a/Macros_1.scala new file mode 100644 index 0000000000..3d39d3e40a --- /dev/null +++ b/test/files/run/t6394a/Macros_1.scala @@ -0,0 +1,12 @@ +import scala.reflect.macros.Context + +object Macros { + def impl(c:Context): c.Expr[Any] = { + import c.universe._ + + val selfTree = This(c.enclosingClass.symbol.asModule.moduleClass) + c.Expr[AnyRef](selfTree) + } + + def foo: Any = macro impl +}
\ No newline at end of file diff --git a/test/files/run/t6394a/Test_2.scala b/test/files/run/t6394a/Test_2.scala new file mode 100644 index 0000000000..75e84f0e38 --- /dev/null +++ b/test/files/run/t6394a/Test_2.scala @@ -0,0 +1,4 @@ +object Test extends App { + println(Macros.foo) + override def toString = "TEST" +}
\ No newline at end of file diff --git a/test/files/run/typetags_without_scala_reflect_manifest_lookup.check b/test/files/run/typetags_without_scala_reflect_manifest_lookup.check new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/files/run/typetags_without_scala_reflect_manifest_lookup.check diff --git a/test/files/run/typetags_without_scala_reflect_manifest_lookup.scala b/test/files/run/typetags_without_scala_reflect_manifest_lookup.scala new file mode 100644 index 0000000000..37047e7884 --- /dev/null +++ b/test/files/run/typetags_without_scala_reflect_manifest_lookup.scala @@ -0,0 +1,29 @@ +import scala.tools.partest._ +import scala.tools.nsc.Settings + +object Test extends DirectTest { + override def extraSettings = "-cp " + sys.props("partest.lib") + + def code = """ + object Test extends App { + // manifest lookup also involves type tag lookup + // because we support manifest <-> typetag convertability + // + // however when scala-reflect.jar (the home of type tags) is not on the classpath + // we need to omit the type tag lookup, because we lack the necessary symbols + // to do implicit search and tag materialization + // (such missing symbols are e.g. ApiUniverseClass and TypeTagsClass) + // + // the test case you're looking at checks exactly this + // we establish a classpath that only includes scala-library.jar + // and then force scalac to perform implicit search for a manifest + // if type tag lookup is not disabled, the compiler will crash + // if it is disabled, then the compilation will succeed + // http://groups.google.com/group/scala-internals/browse_thread/thread/166ce4b71b7c46bb + def foo[T: Manifest] = () + foo[List[Int]] + } + """ + + def show = compile() +}
\ No newline at end of file diff --git a/test/files/run/typetags_without_scala_reflect_typetag_lookup.check b/test/files/run/typetags_without_scala_reflect_typetag_lookup.check new file mode 100644 index 0000000000..f6b82c33f6 --- /dev/null +++ b/test/files/run/typetags_without_scala_reflect_typetag_lookup.check @@ -0,0 +1,3 @@ +newSource1:9: error: could not find implicit value for evidence parameter of type reflect.runtime.package.universe.TypeTag[Int]
+ Library.foo[Int]
+ ^
diff --git a/test/files/run/typetags_without_scala_reflect_typetag_lookup.scala b/test/files/run/typetags_without_scala_reflect_typetag_lookup.scala new file mode 100644 index 0000000000..e51ecdb180 --- /dev/null +++ b/test/files/run/typetags_without_scala_reflect_typetag_lookup.scala @@ -0,0 +1,45 @@ +import scala.tools.partest._ + +object Test extends DirectTest { + def code = ??? + + def library = """ + import scala.reflect.runtime.universe._ + + object Library { + def foo[T: TypeTag] = () + } + """ + def compileLibrary() = { + val classpath = List(sys.props("partest.lib"), sys.props("partest.reflect")) mkString sys.props("path.separator") + compileString(newCompiler("-cp", classpath, "-d", testOutput.path))(library) + } + + def app = """ + object Test extends App { + // tries to materialize a type tag not having scala-reflect.jar on the classpath + // even though it's easy to materialize a type tag of Int, this line will fail + // because materialization involves classes from scala-reflect.jar + // + // in this test we make sure that the compiler doesn't crash + // but just displays several missing class file errors and an unavailable implicit message + Library.foo[Int] + } + """ + def compileApp() = { + val classpath = List(sys.props("partest.lib"), testOutput.path) mkString sys.props("path.separator") + compileString(newCompiler("-cp", classpath, "-d", testOutput.path))(app) + } + + def show(): Unit = { + val prevErr = System.err + val baos = new java.io.ByteArrayOutputStream(); + System.setErr(new java.io.PrintStream(baos)); + compileLibrary(); + compileApp(); + // we should get bad symbolic reference errors, because we're trying to call a method that can't be unpickled + // but we don't know the number of these errors and their order, so I just ignore them all + baos.toString.split("\n") filter (!_.startsWith("error: bad symbolic reference")) foreach println + System.setErr(prevErr) + } +}
\ No newline at end of file diff --git a/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.check b/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.check new file mode 100644 index 0000000000..34f1d84299 --- /dev/null +++ b/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.check @@ -0,0 +1,3 @@ +newSource1:9: error: No Manifest available for App.this.T.
+ manifest[T]
+ ^
diff --git a/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.scala b/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.scala new file mode 100644 index 0000000000..e984127583 --- /dev/null +++ b/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.scala @@ -0,0 +1,46 @@ +import scala.tools.partest._ + +object Test extends DirectTest { + def code = ??? + + def library = """ + import scala.reflect.runtime.universe._ + + trait Library { + type T + implicit val tt: TypeTag[T] + } + """ + def compileLibrary() = { + val classpath = List(sys.props("partest.lib"), sys.props("partest.reflect")) mkString sys.props("path.separator") + compileString(newCompiler("-cp", classpath, "-d", testOutput.path))(library) + } + + def app = """ + trait App extends Library { + // tries to create a manifest from a type tag without having scala-reflect.jar on the classpath + // even though it's possible to convert a type tag into a manifest, this will fail + // because conversion requires classes from scala-reflect.jar + // + // in this test we make sure that the compiler doesn't crash + // but just displays several missing class file errors and an unavailable implicit message + manifest[T] + } + """ + def compileApp() = { + val classpath = List(sys.props("partest.lib"), testOutput.path) mkString sys.props("path.separator") + compileString(newCompiler("-cp", classpath, "-d", testOutput.path))(app) + } + + def show(): Unit = { + val prevErr = System.err + val baos = new java.io.ByteArrayOutputStream(); + System.setErr(new java.io.PrintStream(baos)); + compileLibrary(); + compileApp(); + // we should get bad symbolic reference errors, because we're trying to use an implicit that can't be unpickled + // but we don't know the number of these errors and their order, so I just ignore them all + baos.toString.split("\n") filter (!_.startsWith("error: bad symbolic reference")) foreach println + System.setErr(prevErr) + } +}
\ No newline at end of file diff --git a/test/files/scalacheck/duration.scala b/test/files/scalacheck/duration.scala new file mode 100644 index 0000000000..5e93638614 --- /dev/null +++ b/test/files/scalacheck/duration.scala @@ -0,0 +1,69 @@ +import org.scalacheck._ +import Prop._ +import Gen._ +import Arbitrary._ +import math._ +import concurrent.duration.Duration.fromNanos + +object Test extends Properties("Division of Duration by Long") { + + val weightedLong = + frequency( + 1 -> choose(-128L, 127L), + 1 -> (arbitrary[Byte] map (_.toLong << 8)), + 1 -> (arbitrary[Byte] map (_.toLong << 16)), + 1 -> (arbitrary[Byte] map (_.toLong << 24)), + 1 -> (arbitrary[Byte] map (_.toLong << 32)), + 1 -> (arbitrary[Byte] map (_.toLong << 40)), + 1 -> (arbitrary[Byte] map (_.toLong << 48)), + 1 -> (choose(-127L, 127L) map (_ << 56)) + ) + + val genTwoSmall = for { + a <- weightedLong + b <- choose(-(Long.MaxValue / max(1, abs(a))), Long.MaxValue / max(1, abs(a))) + } yield (a, b) + + val genTwoLarge = for { + a <- weightedLong + b <- arbitrary[Long] suchThat (b => (abs(b) > Long.MaxValue / max(1, abs(a)))) + } yield (a, b) + + val genClose = for { + a <- weightedLong + if a != 0 + b <- choose(Long.MaxValue / a - 10, Long.MaxValue / a + 10) + } yield (a, b) + + val genBorderline = + frequency( + 1 -> (Long.MinValue, 0L), + 1 -> (Long.MinValue, 1L), + 1 -> (Long.MinValue, -1L), + 1 -> (0L, Long.MinValue), + 1 -> (1L, Long.MinValue), + 1 -> (-1L, Long.MinValue), + 90 -> genClose + ) + + def mul(a: Long, b: Long): Long = { + (fromNanos(a) * b).toNanos + } + + property("without overflow") = forAll(genTwoSmall) { case (a, b) => + a * b == mul(a, b) + } + + property("with overflow") = forAll(genTwoLarge) { case (a, b) => + try { mul(a, b); false } catch { case _: IllegalArgumentException => true } + } + + property("on overflow edge cases") = forAll(genBorderline) { case (a, b) => + val shouldFit = + a != Long.MinValue && // must fail due to illegal duration length + (b != Long.MinValue || a == 0) && // Long factor may only be MinValue if the duration is zero, otherwise the result will be illegal + (abs(b) <= Long.MaxValue / max(1, abs(a))) // check the rest against the “safe” division method + try { mul(a, b); shouldFit } + catch { case _: IllegalArgumentException => !shouldFit } + } +} diff --git a/test/osgi/src/BasicLibrary.scala b/test/osgi/src/BasicLibrary.scala new file mode 100644 index 0000000000..38dea69e99 --- /dev/null +++ b/test/osgi/src/BasicLibrary.scala @@ -0,0 +1,37 @@ +package tools.test.osgi +package libonly + +import org.junit.Assert._ +import org.ops4j.pax.exam.CoreOptions._ + +import org.junit.Test +import org.junit.runner.RunWith +import org.ops4j.pax.exam +import org.ops4j.pax.exam.junit.{ + Configuration, + ExamReactorStrategy, + JUnit4TestRunner +} +import org.ops4j.pax.exam.spi.reactors.AllConfinedStagedReactorFactory +import org.ops4j.pax.swissbox.framework.ServiceLookup +import org.osgi.framework.BundleContext + + + +@RunWith(classOf[JUnit4TestRunner]) +@ExamReactorStrategy(Array(classOf[AllConfinedStagedReactorFactory])) +class BasicLibraryTest extends ScalaOsgiHelper { + @Configuration + def config(): Array[exam.Option] = + justCoreLibraryOptions + + @Test + def everythingLoads(): Unit = { + // Note - This tests sun.misc usage. + import scala.concurrent._ + import scala.concurrent.util.Duration.Inf + import ExecutionContext.Implicits._ + val x = Future(2) map (_ + 1) + assertEquals(3, Await.result(x, Inf)) + } +} diff --git a/test/osgi/src/BasicReflection.scala b/test/osgi/src/BasicReflection.scala new file mode 100644 index 0000000000..8a0a05d531 --- /dev/null +++ b/test/osgi/src/BasicReflection.scala @@ -0,0 +1,66 @@ +package tools.test.osgi +package reflection +package basic + +import org.junit.Assert._ +import org.ops4j.pax.exam.CoreOptions._ + +import org.junit.Test +import org.junit.runner.RunWith +import org.ops4j.pax.exam +import org.ops4j.pax.exam.junit.{ + Configuration, + ExamReactorStrategy, + JUnit4TestRunner +} +import org.ops4j.pax.exam.spi.reactors.AllConfinedStagedReactorFactory +import org.ops4j.pax.swissbox.framework.ServiceLookup +import org.osgi.framework.BundleContext + + +class C { + val f1 = 2 + var f2 = 3 + + def m1 = 4 + def m2() = 5 + def m3[T >: String <: Int]: T = ??? + def m4[A[_], B <: A[Int]](x: A[B])(implicit y: Int) = ??? + def m5(x: => Int, y: Int*): String = ??? + + class C + object M + + override def toString = "an instance of C" +} +object M + + +@RunWith(classOf[JUnit4TestRunner]) +@ExamReactorStrategy(Array(classOf[AllConfinedStagedReactorFactory])) +class BasicReflectionTest extends ScalaOsgiHelper { + + @Configuration + def config(): Array[exam.Option] = + justReflectionOptions + + // Ensure Pax-exam requires C/M in our module + def dummy = { + new C + M.toString + } + + @Test + def basicMirrorThroughOsgi(): Unit = { + // Note for now just assert that we can do this stuff. + import scala.reflect.runtime.universe._ + val cm = runtimeMirror(classOf[C].getClassLoader) + val im = cm.reflect(new C) + assertEquals("Unable to reflect field name!", + "value f1", + im.reflectField(typeOf[C].member(newTermName("f1")).asTerm).symbol.toString) + assertEquals("Unable to reflect value!", + 2, + im.reflectField(typeOf[C].member(newTermName("f1")).asTerm).get) + } +} diff --git a/test/osgi/src/BasicTest.scala b/test/osgi/src/BasicTest.scala new file mode 100644 index 0000000000..109b7b911a --- /dev/null +++ b/test/osgi/src/BasicTest.scala @@ -0,0 +1,33 @@ +package tools.test.osgi + +import org.junit.Assert._ +import org.ops4j.pax.exam.CoreOptions._ + +import org.junit.Test +import org.junit.runner.RunWith +import org.ops4j.pax.exam +import org.ops4j.pax.exam.junit.{ + Configuration, + ExamReactorStrategy, + JUnit4TestRunner +} +import org.ops4j.pax.exam.spi.reactors.AllConfinedStagedReactorFactory +import org.ops4j.pax.swissbox.framework.ServiceLookup +import org.osgi.framework.BundleContext + + + + + +@RunWith(classOf[JUnit4TestRunner]) +@ExamReactorStrategy(Array(classOf[AllConfinedStagedReactorFactory])) +class BasicTest extends ScalaOsgiHelper { + @Configuration + def config(): Array[exam.Option] = { + // TODO - Find scala bundles. + standardOptions + } + + @Test + def everythingLoads(): Unit = () +} diff --git a/test/osgi/src/ReflectionToolboxTest.scala b/test/osgi/src/ReflectionToolboxTest.scala new file mode 100644 index 0000000000..bb48078e95 --- /dev/null +++ b/test/osgi/src/ReflectionToolboxTest.scala @@ -0,0 +1,49 @@ +package tools.test.osgi +package reflection +package toolbox + +import org.junit.Assert._ +import org.ops4j.pax.exam.CoreOptions._ + +import org.junit.Test +import org.junit.runner.RunWith +import org.ops4j.pax.exam +import org.ops4j.pax.exam.junit.{ + Configuration, + ExamReactorStrategy, + JUnit4TestRunner +} +import org.ops4j.pax.exam.spi.reactors.AllConfinedStagedReactorFactory +import org.ops4j.pax.swissbox.framework.ServiceLookup +import org.osgi.framework.BundleContext + + +class C { + val f1 = 2 +} + +@RunWith(classOf[JUnit4TestRunner]) +@ExamReactorStrategy(Array(classOf[AllConfinedStagedReactorFactory])) +class ReflectionToolBoxTest extends ScalaOsgiHelper { + + @Configuration + def config(): Array[exam.Option] = + standardOptions + + + @Test + def basicMirrorThroughOsgi(): Unit = { + // Note - this tries to make sure when pulling a toolbox, we get the compiler. + import scala.reflect.runtime.universe._ + import scala.tools.reflect.ToolBox + val cm = runtimeMirror(classOf[C].getClassLoader) + val tb = cm.mkToolBox() + val im = cm.reflect(new C) + val tree = tb.parse("1 to 3 map (_+1)") + val eval = tb.eval(tree) + assertEquals(Vector(2, 3, 4), eval) + assertEquals("Evaluate expression using local class.", + 2, + tb.eval(tb.parse("(new tools.test.osgi.reflection.toolbox.C).f1"))) + } +} diff --git a/test/osgi/src/ScalaOsgiHelper.scala b/test/osgi/src/ScalaOsgiHelper.scala new file mode 100644 index 0000000000..bcdc5c0df1 --- /dev/null +++ b/test/osgi/src/ScalaOsgiHelper.scala @@ -0,0 +1,36 @@ +package tools.test.osgi + +import org.ops4j.pax.exam.CoreOptions._ +import org.ops4j.pax.exam +import java.io.File + +trait ScalaOsgiHelper { + + private def allBundleFiles = { + def bundleLocation = new File(sys.props.getOrElse("scala.bundle.dir", "build/osgi")) + bundleLocation.listFiles filter (_.getName endsWith ".jar") + } + + private def filteredBundleFiles(names: String*): Array[exam.Option] = + for(bundle <- allBundleFiles; if names exists (bundle.getName contains)) + yield makeBundle(bundle) + + private def makeBundle(file: File): exam.Option = + bundle(file.toURI.toASCIIString) + + def standardOptions: Array[exam.Option] = { + val bundles = (allBundleFiles map makeBundle) + bundles ++ Array[exam.Option](felix(), equinox(), junitBundles()) + } + + def justReflectionOptions: Array[exam.Option] = { + val bundles = filteredBundleFiles("scala-library", "scala-reflect") + bundles ++ Array[exam.Option](felix(), equinox(), junitBundles()) + } + + def justCoreLibraryOptions: Array[exam.Option] = { + val bundles = filteredBundleFiles("scala-library") + bundles ++ Array[exam.Option](felix(), equinox(), junitBundles()) + } + +} diff --git a/tools/binary-repo-lib.sh b/tools/binary-repo-lib.sh index d43f3c8bff..4fe6dd67a0 100755 --- a/tools/binary-repo-lib.sh +++ b/tools/binary-repo-lib.sh @@ -191,7 +191,7 @@ pullJarFileToCache() { if [[ ! -f "$cache_loc" ]]; then # Note: After we follow up with JFrog, we should check the more stable raw file server first # before hitting the more flaky artifactory. - curlDownload $cache_loc ${remote_urlpush}/${uri} + curlDownload $cache_loc ${remote_urlget}/${uri} if test "$(checkJarSha "$cache_loc" "$sha")" != "OK"; then echo "Trouble downloading $uri. Please try pull-binary-libs again when your internet connection is stable." exit 2 |