diff --git a/compile/CompilerArguments.scala b/compile/CompilerArguments.scala
index 8233c9f1d..cd27b15b5 100644
--- a/compile/CompilerArguments.scala
+++ b/compile/CompilerArguments.scala
@@ -22,7 +22,7 @@ class CompilerArguments(scalaInstance: ScalaInstance, cp: ClasspathOptions) exte
def finishClasspath(classpath: Set[File]): Set[File] =
classpath ++ include(cp.compiler, scalaInstance.compilerJar) ++ include(cp.extra, scalaInstance.extraJars : _*)
private def include(flag: Boolean, jars: File*) = if(flag) jars else Nil
- protected def abs(files: Set[File]) = files.map(_.getAbsolutePath).toList.sort(_ < _)
+ protected def abs(files: Set[File]) = files.map(_.getAbsolutePath).toList.sortWith(_ < _)
protected def checkScalaHomeUnset()
{
val scalaHome = System.getProperty("scala.home")
diff --git a/compile/ComponentCompiler.scala b/compile/ComponentCompiler.scala
index 24a744990..b36a33bb8 100644
--- a/compile/ComponentCompiler.scala
+++ b/compile/ComponentCompiler.scala
@@ -18,7 +18,7 @@ object ComponentCompiler
class ComponentCompiler(compiler: RawCompiler, manager: ComponentManager)
{
import ComponentCompiler._
- import FileUtilities.{copy, createDirectory, zip, jars, unzip, withTemporaryDirectory}
+ import sbt.IO.{copy, createDirectory, zip, jars, unzip, withTemporaryDirectory}
def apply(id: String): File =
try { getPrecompiled(id) }
catch { case _: InvalidComponent => getLocallyCompiled(id) }
@@ -55,7 +55,6 @@ class ComponentCompiler(compiler: RawCompiler, manager: ComponentManager)
val isSource = (f: File) => isSourceName(f.getName)
def keepIfSource(files: Set[File]): Set[File] = if(files.exists(isSource)) files else Set()
- import Paths._
withTemporaryDirectory { dir =>
val extractedSources = (Set[File]() /: sourceJars) { (extracted, sourceJar)=> extracted ++ keepIfSource(unzip(sourceJar, dir)) }
val (sourceFiles, resources) = extractedSources.partition(isSource)
@@ -69,8 +68,9 @@ class ComponentCompiler(compiler: RawCompiler, manager: ComponentManager)
manager.log.info(" Compilation completed in " + (System.currentTimeMillis - start) / 1000.0 + " s")
}
catch { case e: xsbti.CompileFailed => throw new CompileFailed(e.arguments, "Error compiling sbt component '" + id + "'") }
- copy(resources x (FileMapper.rebase(dir, outputDirectory)))
- zip((outputDirectory ***) x (PathMapper.relativeTo(outputDirectory)), targetJar)
+ import sbt.Path._
+ copy(resources x rebase(dir, outputDirectory))
+ zip((outputDirectory ***) x relativeTo(outputDirectory), targetJar)
}
}
}
diff --git a/compile/RawCompiler.scala b/compile/RawCompiler.scala
index ec91eb181..6b25079fc 100644
--- a/compile/RawCompiler.scala
+++ b/compile/RawCompiler.scala
@@ -19,7 +19,7 @@ class RawCompiler(val scalaInstance: ScalaInstance, cp: ClasspathOptions, log: C
log.debug("Plain interface to Scala compiler " + scalaInstance.actualVersion + " with arguments: " + arguments.mkString("\n\t", "\n\t", ""))
val mainClass = Class.forName("scala.tools.nsc.Main", true, scalaInstance.loader)
val process = mainClass.getMethod("process", classOf[Array[String]])
- process.invoke(null, toJavaArray(arguments))
+ process.invoke(null, arguments.toArray)
checkForFailure(mainClass, arguments.toArray)
}
def compilerArguments = new CompilerArguments(scalaInstance, cp)
@@ -29,12 +29,6 @@ class RawCompiler(val scalaInstance: ScalaInstance, cp: ClasspathOptions, log: C
val failed = reporter.getClass.getMethod("hasErrors").invoke(reporter).asInstanceOf[Boolean]
if(failed) throw new CompileFailed(args, "Plain compile failed")
}
- protected def toJavaArray(arguments: Seq[String]): Array[String] =
- {
- val realArray: Array[String] = arguments.toArray
- assert(realArray.getClass eq classOf[Array[String]])
- realArray
- }
}
class CompileFailed(val arguments: Array[String], override val toString: String) extends xsbti.CompileFailed
{
diff --git a/compile/api/SameAPI.scala b/compile/api/SameAPI.scala
index 1c7d2dc2c..bbcd419ba 100644
--- a/compile/api/SameAPI.scala
+++ b/compile/api/SameAPI.scala
@@ -48,7 +48,7 @@ object SameAPI
}
def separateDefinitions(s: Seq[Definition]): (Seq[Definition], Seq[Definition]) =
- s.toArray.partition(isValueDefinition)
+ s.partition(isValueDefinition)
def isValueDefinition(d: Definition): Boolean =
d match
{
@@ -59,12 +59,12 @@ object SameAPI
def isValue(d: DefinitionType): Boolean =
d == DefinitionType.Module || d == DefinitionType.PackageModule
/** Puts the given definitions in a map according to their names.*/
- def byName(s: Seq[Definition]): scala.collection.Map[String, List[Definition]] =
+ def byName(s: Seq[Definition]): Map[String, List[Definition]] =
{
- val map = new mutable.HashMap[String, List[Definition]]
+ var map = Map[String, List[Definition]]()
for(d <- s; name = d.name)
- map(name) = d :: map.getOrElse(name, Nil)
- map.readOnly
+ map = map.updated(name, d :: map.getOrElse(name, Nil) )
+ map
}
}
/** Used to implement API equality. All comparisons must be done between constructs in source files `a` and `b`. For example, when doing:
@@ -358,7 +358,5 @@ private class SameAPI(a: Source, b: Source, includePrivate: Boolean)
def sameStrings(a: scala.collection.Set[String], b: scala.collection.Set[String]): Boolean =
a == b
final def sameSeq[T](a: Seq[T], b: Seq[T])(eq: (T,T) => Boolean): Boolean =
- sameArray(a.toArray, b.toArray)(eq)
- final def sameArray[T](a: Array[T], b: Array[T])(eq: (T,T) => Boolean): Boolean =
(a.length == b.length) && (a zip b).forall(tupled(eq))
}
\ No newline at end of file
diff --git a/compile/interface/API.scala b/compile/interface/API.scala
index d0261a635..997ece0dc 100644
--- a/compile/interface/API.scala
+++ b/compile/interface/API.scala
@@ -9,13 +9,16 @@ import io.{AbstractFile, PlainFile, ZipArchive}
import plugins.{Plugin, PluginComponent}
import symtab.Flags
import scala.collection.mutable.{HashMap, HashSet, ListBuffer}
-//import xsbti.api.{ClassLike, DefinitionType, PathComponent, SimpleType}
+import xsbti.api.{ClassLike, DefinitionType, PathComponent, SimpleType}
object API
{
val name = "xsbt-api"
+ // for 2.7 compatibility: this class was removed in 2.8
+ type ImplicitMethodType = AnyRef
}
-final class API(val global: Global, val callback: xsbti.AnalysisCallback) extends NotNull
+import API._ // imports ImplicitMethodType, which will preserve source compatibility in 2.7 for defDef
+final class API(val global: Global, val callback: xsbti.AnalysisCallback) extends Compat
{
import global._
def error(msg: String) = throw new RuntimeException(msg)
@@ -35,7 +38,7 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend
println("API phase took : " + ((stop - start)/1000.0) + " s")
}
}
- /*def processUnit(unit: CompilationUnit)
+ def processUnit(unit: CompilationUnit)
{
val sourceFile = unit.source.file.file
val traverser = new TopLevelHandler(sourceFile)
@@ -43,9 +46,9 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend
val packages = traverser.packages.toArray[String].map(p => new xsbti.api.Package(p))
val source = new xsbti.api.Source(packages, traverser.definitions.toArray[xsbti.api.Definition])
callback.api(sourceFile, source)
- }*/
+ }
}
- /*private def thisPath(sym: Symbol) = path(pathComponents(sym, Constants.thisPath :: Nil))
+ private def thisPath(sym: Symbol) = path(pathComponents(sym, Constants.thisPath :: Nil))
private def path(components: List[PathComponent]) = new xsbti.api.Path(components.toArray[PathComponent])
private def pathComponents(sym: Symbol, postfix: List[PathComponent]): List[PathComponent] =
{
@@ -64,7 +67,7 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend
if(pre == NoPrefix)
{
if(sym.isLocalClass) Constants.emptyType
- else if(sym.isTypeParameterOrSkolem || sym.isExistential) new xsbti.api.ParameterRef(sym.id)
+ else if(sym.isTypeParameterOrSkolem || isExistential(sym)) new xsbti.api.ParameterRef(sym.id)
else error("Unknown prefixless type: " + sym)
}
else if(sym.isRoot || sym.isRootPackage) Constants.emptyType
@@ -178,7 +181,7 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend
{
if(sym.isClass) classLike(sym)
else if(sym.isMethod) defDef(sym)
- else if(sym.isTypeMember) typeDef(sym)
+ else if(isNonClassType(sym)) typeDef(sym)
else if(sym.isVariable) fieldDef(sym, new xsbti.api.Var(_,_,_,_,_))
else fieldDef(sym, new xsbti.api.Val(_,_,_,_,_))
}
@@ -316,6 +319,6 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend
val annots = at.attributes
if(annots.isEmpty) processType(at.underlying) else annotated(annots, at.underlying)
}
- private def fullName(s: Symbol): String = s.fullNameString
- private def simpleName(s: Symbol): String = s.simpleName.toString.trim*/
+ private def fullName(s: Symbol): String = nameString(s)
+ private def simpleName(s: Symbol): String = s.simpleName.toString.trim
}
\ No newline at end of file
diff --git a/compile/interface/Analyzer.scala b/compile/interface/Analyzer.scala
index 4b3e99ae4..7159d0624 100644
--- a/compile/interface/Analyzer.scala
+++ b/compile/interface/Analyzer.scala
@@ -17,10 +17,9 @@ object Analyzer
{
def name = "xsbt-analyzer"
}
-final class Analyzer(val global: Global, val callback: AnalysisCallback) extends NotNull
+final class Analyzer(val global: Global, val callback: AnalysisCallback) extends Compat
{
import global._
- import Compat.{archive, hasAnnotation, linkedClass, nameString}
def newPhase(prev: Phase): Phase = new AnalyzerPhase(prev)
private class AnalyzerPhase(prev: Phase) extends Phase(prev)
@@ -216,35 +215,42 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends
if(entry eq null) None else Some(entry.classFile)
}
}
- private object Compat
+}
+abstract class Compat
+{
+ val global: Global
+ import global._
+ def archive(s: ZipArchive#Entry): ZipFile = s.getArchive
+ def nameString(s: Symbol): String = s.fullNameString
+ def nameString(s: Symbol, sep: Char): String = s.fullNameString(sep)
+ def isExistential(s: Symbol): Boolean = s.isExistential
+ def isNonClassType(s: Symbol): Boolean = s.isTypeMember
+
+ def linkedClass(s: Symbol): Symbol = s.linkedClassOfModule
+
+ /** After 2.8.0.Beta1, fullNameString was renamed fullName.
+ * linkedClassOfModule was renamed companionClass. */
+ private implicit def symCompat(sym: Symbol): SymCompat = new SymCompat(sym)
+ private final class SymCompat(s: Symbol)
{
- def archive(s: ZipArchive#Entry): ZipFile = s.getArchive
- def nameString(s: Symbol): String = s.fullNameString
- def nameString(s: Symbol, sep: Char): String = s.fullNameString(sep)
-
- def linkedClass(s: Symbol): Symbol = s.linkedClassOfModule
-
- /** After 2.8.0.Beta1, fullNameString was renamed fullName.
- * linkedClassOfModule was renamed companionClass. */
- private implicit def symCompat(sym: Symbol): SymCompat = new SymCompat(sym)
- private final class SymCompat(s: Symbol)
- {
- def fullNameString = s.fullName; def fullName = sourceCompatibilityOnly
- def fullNameString(sep: Char) = s.fullName(sep); def fullName(sep: Char) = sourceCompatibilityOnly
-
- def linkedClassOfModule = s.companionClass; def companionClass = sourceCompatibilityOnly
- // In 2.8, hasAttribute is renamed to hasAnnotation
- def hasAnnotation(a: Symbol) = s.hasAttribute(a); def hasAttribute(a: Symbol) = sourceCompatibilityOnly
- }
-
- def hasAnnotation(s: Symbol)(ann: Symbol) = atPhase(currentRun.typerPhase) { s.hasAnnotation(ann) }
-
- /** After 2.8.0.Beta1, getArchive was renamed archive.*/
- private implicit def zipCompat(z: ZipArchive#Entry): ZipCompat = new ZipCompat(z)
- private final class ZipCompat(z: ZipArchive#Entry)
- {
- def getArchive = z.archive; def archive = sourceCompatibilityOnly
- }
- private def sourceCompatibilityOnly = error("For source compatibility only: should not get here.")
+ def fullNameString = s.fullName; def fullName = sourceCompatibilityOnly
+ def fullNameString(sep: Char) = s.fullName(sep); def fullName(sep: Char) = sourceCompatibilityOnly
+
+ def isExistential: Boolean = s.isExistentiallyBound; def isExistentiallyBound = sourceCompatibilityOnly
+ def isTypeMember: Boolean = s.isNonClassType; def isNonClassType = sourceCompatibilityOnly
+
+ def linkedClassOfModule = s.companionClass; def companionClass = sourceCompatibilityOnly
+ // In 2.8, hasAttribute is renamed to hasAnnotation
+ def hasAnnotation(a: Symbol) = s.hasAttribute(a); def hasAttribute(a: Symbol) = sourceCompatibilityOnly
}
+
+ def hasAnnotation(s: Symbol)(ann: Symbol) = atPhase(currentRun.typerPhase) { s.hasAnnotation(ann) }
+
+ /** After 2.8.0.Beta1, getArchive was renamed archive.*/
+ private implicit def zipCompat(z: ZipArchive#Entry): ZipCompat = new ZipCompat(z)
+ private final class ZipCompat(z: ZipArchive#Entry)
+ {
+ def getArchive = z.archive; def archive = sourceCompatibilityOnly
+ }
+ private def sourceCompatibilityOnly = error("For source compatibility only: should not get here.")
}
\ No newline at end of file
diff --git a/ivy/ComponentManager.scala b/ivy/ComponentManager.scala
index 79b83fc32..6e6e3d95e 100644
--- a/ivy/ComponentManager.scala
+++ b/ivy/ComponentManager.scala
@@ -25,7 +25,7 @@ class ComponentManager(globalLock: xsbti.GlobalLock, provider: xsbti.ComponentPr
try { update(id); getOrElse(createAndCache) }
catch { case e: NotInCache => createAndCache }
}
- def getOrElse(orElse: => Iterable[File]) =
+ def getOrElse(orElse: => Iterable[File]): Iterable[File] =
{
val existing = provider.component(id)
if(existing.isEmpty) orElse else existing
diff --git a/ivy/CustomXmlParser.scala b/ivy/CustomXmlParser.scala
index a8b7d9b43..f773b1ce9 100644
--- a/ivy/CustomXmlParser.scala
+++ b/ivy/CustomXmlParser.scala
@@ -14,10 +14,10 @@ import plugins.repository.Resource
import plugins.repository.url.URLResource
/** Subclasses the default Ivy file parser in order to provide access to protected methods.*/
-private[sbt] object CustomXmlParser extends XmlModuleDescriptorParser with NotNull
+private[sbt] object CustomXmlParser extends XmlModuleDescriptorParser
{
import XmlModuleDescriptorParser.Parser
- class CustomParser(settings: IvySettings, defaultConfig: Option[String]) extends Parser(CustomXmlParser, settings) with NotNull
+ class CustomParser(settings: IvySettings, defaultConfig: Option[String]) extends Parser(CustomXmlParser, settings)
{
if(defaultConfig.isDefined) setDefaultConfMapping("*->default(compile)")
diff --git a/ivy/Ivy.scala b/ivy/Ivy.scala
index b2d59c60d..e0d880a94 100644
--- a/ivy/Ivy.scala
+++ b/ivy/Ivy.scala
@@ -257,13 +257,7 @@ private object IvySbt
javaMap(ea.extraAttributes)
}
private def javaMap(map: Map[String,String]) =
- if(map.isEmpty) null
- else
- {
- val wrap = scala.collection.jcl.Map(new java.util.HashMap[String,String])
- wrap ++= map
- wrap.underlying
- }
+ if(map.isEmpty) null else scala.collection.JavaConversions.asMap(map)
private object javaMap
{
@@ -337,7 +331,7 @@ private object IvySbt
lazy val allConfigurations = moduleID.getPublicConfigurationsNames
for(artifact <- artifacts)
{
- val configurationStrings =
+ val configurationStrings: Iterable[String] =
{
val artifactConfigurations = artifact.configurations
if(artifactConfigurations.isEmpty)
diff --git a/ivy/IvyActions.scala b/ivy/IvyActions.scala
index d80b12e13..b566258a5 100644
--- a/ivy/IvyActions.scala
+++ b/ivy/IvyActions.scala
@@ -60,8 +60,6 @@ object IvyActions
}
/** Creates a Maven pom from the given Ivy configuration*/
- @deprecated def makePom(module: IvySbt#Module, extraDependencies: Iterable[ModuleID], configurations: Option[Iterable[Configuration]], extra: NodeSeq, output: File): Unit =
- makePom(module, MakePomConfiguration(extraDependencies, configurations, extra), output)
def makePom(module: IvySbt#Module, configuration: MakePomConfiguration, output: File)
{
import configuration.{configurations, extra, extraDependencies, filterRepositories, process}
@@ -127,7 +125,7 @@ object IvyActions
resolveOptions.setLog(ivyLogLevel(logging))
val resolveReport = ivy.resolve(module, resolveOptions)
if(resolveReport.hasError)
- throw new ResolveException(resolveReport.getAllProblemMessages.toArray.map(_.toString).toList.removeDuplicates)
+ throw new ResolveException(resolveReport.getAllProblemMessages.toArray.map(_.toString).distinct)
}
import UpdateLogging.{Quiet, Full, DownloadOnly}
@@ -140,4 +138,4 @@ object IvyActions
case Full => LOG_DEFAULT
}
}
-final class ResolveException(messages: List[String]) extends RuntimeException(messages.mkString("\n"))
\ No newline at end of file
+final class ResolveException(messages: Seq[String]) extends RuntimeException(messages.mkString("\n"))
\ No newline at end of file
diff --git a/launch/Boot.scala b/launch/Boot.scala
index 3e246cafe..2bda82e66 100644
--- a/launch/Boot.scala
+++ b/launch/Boot.scala
@@ -27,7 +27,7 @@ object Boot
catch
{
case b: BootException => errorAndExit(b.toString)
- case r: xsbti.RetrieveException =>errorAndExit("Error: " + r.getMessage)
+ case r: xsbti.RetrieveException => errorAndExit("Error: " + r.getMessage)
case r: xsbti.FullReload => r.arguments
case e =>
e.printStackTrace
diff --git a/launch/Configuration.scala b/launch/Configuration.scala
index f4c6180be..9168986ad 100644
--- a/launch/Configuration.scala
+++ b/launch/Configuration.scala
@@ -6,6 +6,7 @@ package xsbt.boot
import Pre._
import java.io.{File, FileInputStream, InputStreamReader}
import java.net.{MalformedURLException, URI, URL}
+import scala.collection.immutable.List
object Configuration
{
@@ -21,7 +22,7 @@ object Configuration
}
def configurationOnClasspath: URL =
{
- resourcePaths.elements.map(getClass.getResource).find(_ ne null) getOrElse
+ resourcePaths.iterator.map(getClass.getResource).find(_ ne null) getOrElse
( multiPartError("Could not finder sbt launch configuration. Searched classpath for:", resourcePaths))
}
def directConfiguration(path: String, baseDirectory: File): URL =
@@ -39,7 +40,7 @@ object Configuration
}
val against = resolveAgainst(baseDirectory)
// use Iterators so that resolution occurs lazily, for performance
- val resolving = against.elements.flatMap(e => resolve(e).toList.elements)
+ val resolving = against.iterator.flatMap(e => resolve(e).toList.iterator)
if(!resolving.hasNext) multiPartError("Could not find configuration file '" + path + "'. Searched:", against)
resolving.next()
}
@@ -49,9 +50,9 @@ object Configuration
val JarBasePath = "/sbt/"
def userConfigurationPath = "/" + ConfigurationName
def defaultConfigurationPath = JarBasePath + ConfigurationName
- def resourcePaths: List[String] = List(userConfigurationPath, defaultConfigurationPath)
- def resolveAgainst(baseDirectory: File): List[URI] = List(baseDirectory toURI, new File(System.getProperty("user.home")) toURI,
- toDirectory(classLocation(getClass).toURI))
+ def resourcePaths: List[String] = userConfigurationPath :: defaultConfigurationPath :: Nil
+ def resolveAgainst(baseDirectory: File): List[URI] = (baseDirectory toURI) :: (new File(System.getProperty("user.home")) toURI) ::
+ toDirectory(classLocation(getClass).toURI) :: Nil
def classLocation(cl: Class[_]): URL =
{
diff --git a/launch/ConfigurationParser.scala b/launch/ConfigurationParser.scala
index 242681fe4..c7e702249 100644
--- a/launch/ConfigurationParser.scala
+++ b/launch/ConfigurationParser.scala
@@ -9,6 +9,7 @@ import java.lang.Character.isWhitespace
import java.io.{BufferedReader, File, FileInputStream, InputStreamReader, Reader, StringReader}
import java.net.{MalformedURLException, URL}
import java.util.regex.Pattern
+import scala.collection.immutable.List
class ConfigurationParser extends NotNull
{
diff --git a/launch/Create.scala b/launch/Create.scala
index 488790631..3434938ca 100644
--- a/launch/Create.scala
+++ b/launch/Create.scala
@@ -6,6 +6,7 @@ package xsbt.boot
import Pre._
import java.io.{File, FileInputStream, FileOutputStream}
import java.util.Properties
+import scala.collection.immutable.List
object Initialize
{
@@ -41,7 +42,7 @@ object Initialize
if(!uninitialized.isEmpty)
{
file.getParentFile.mkdirs()
- Using(new FileOutputStream(file))( out => properties.save(out, "") )
+ Using(new FileOutputStream(file))( out => properties.store(out, "") )
}
}
def initialize(properties: Properties, name: String, init: PropertyInit)
diff --git a/launch/Enumeration.scala b/launch/Enumeration.scala
index 046227e03..cb994f1e9 100644
--- a/launch/Enumeration.scala
+++ b/launch/Enumeration.scala
@@ -4,6 +4,7 @@
package xsbt.boot
import Pre._
+import scala.collection.immutable.List
class Enumeration extends NotNull
{
@@ -25,6 +26,5 @@ class Enumeration extends NotNull
def value(s: String) = new Value(s, 0)
def value(s: String, i: Int) = new Value(s, i)
class Value(override val toString: String, val id: Int) extends NotNull
-
def toValue(s: String): Value = elements.find(_.toString == s).getOrElse(error("Expected one of " + elements.mkString(",") + " (got: " + s + ")"))
}
\ No newline at end of file
diff --git a/launch/FilteredLoader.scala b/launch/FilteredLoader.scala
index 53ad52d66..6b318066e 100644
--- a/launch/FilteredLoader.scala
+++ b/launch/FilteredLoader.scala
@@ -4,10 +4,11 @@
package xsbt.boot
import BootConfiguration.{IvyPackage, JLinePackagePath, SbtBootPackage, ScalaPackage}
+import scala.collection.immutable.Stream
/** A custom class loader to ensure the main part of sbt doesn't load any Scala or
* Ivy classes from the jar containing the loader. */
-private[boot] final class BootFilteredLoader(parent: ClassLoader) extends ClassLoader(parent) with NotNull
+private[boot] final class BootFilteredLoader(parent: ClassLoader) extends ClassLoader(parent)
{
@throws(classOf[ClassNotFoundException])
override final def loadClass(className: String, resolve: Boolean): Class[_] =
diff --git a/launch/Find.scala b/launch/Find.scala
index 39a7a369a..459689950 100644
--- a/launch/Find.scala
+++ b/launch/Find.scala
@@ -6,6 +6,7 @@ package xsbt.boot
import Pre._
import java.io.File
import java.net.URI
+import scala.collection.immutable.List
object Find { def apply(config: LaunchConfiguration, currentDirectory: File) = (new Find(config))(currentDirectory) }
class Find(config: LaunchConfiguration) extends NotNull
diff --git a/launch/Launch.scala b/launch/Launch.scala
index 828f9ca0a..4a4ed9c15 100644
--- a/launch/Launch.scala
+++ b/launch/Launch.scala
@@ -7,6 +7,7 @@ import Pre._
import BootConfiguration.{CompilerModuleName, LibraryModuleName}
import java.io.File
import java.net.URL
+import scala.collection.immutable.List
object Launch
{
diff --git a/launch/LaunchConfiguration.scala b/launch/LaunchConfiguration.scala
index e39d849b6..4b9c333bc 100644
--- a/launch/LaunchConfiguration.scala
+++ b/launch/LaunchConfiguration.scala
@@ -6,6 +6,7 @@ package xsbt.boot
import Pre._
import java.io.File
import java.net.URL
+import scala.collection.immutable.List
final case class LaunchConfiguration(scalaVersion: Version, ivyConfiguration: IvyOptions, app: Application, boot: BootSetup, logging: Logging, appProperties: List[AppProperty]) extends NotNull
{
diff --git a/launch/ListMap.scala b/launch/ListMap.scala
index e35c748c5..0239c5320 100644
--- a/launch/ListMap.scala
+++ b/launch/ListMap.scala
@@ -4,9 +4,11 @@
package xsbt.boot
import Pre._
+import scala.collection.{Iterable, Iterator}
+import scala.collection.immutable.List
// preserves iteration order
-sealed class ListMap[K,V] private(backing: List[(K,V)]) extends Iterable[(K,V)] with NotNull
+sealed class ListMap[K,V] private(backing: List[(K,V)]) extends Traversable[(K,V)] with NotNull
{
import ListMap.remove
def update(k: K, v: V) = this.+( (k,v) )
@@ -16,7 +18,7 @@ sealed class ListMap[K,V] private(backing: List[(K,V)]) extends Iterable[(K,V)]
def keys: List[K] = backing.reverse.map(_._1)
def apply(k: K): V = get(k).getOrElse(error("Key " + k + " not found"))
def contains(k: K): Boolean = get(k).isDefined
- def elements: Iterator[(K,V)] = backing.reverse.elements
+ def foreach[T](f: ((K,V)) => T) = backing.reverse.foreach(f)
override def isEmpty: Boolean = backing.isEmpty
override def toList = backing.reverse
override def toSeq = toList
@@ -30,7 +32,7 @@ sealed class ListMap[K,V] private(backing: List[(K,V)]) extends Iterable[(K,V)]
}
object ListMap
{
- def apply[K,V](pairs: (K,V)*) = new ListMap[K,V](pairs.toList.removeDuplicates)
+ def apply[K,V](pairs: (K,V)*) = new ListMap[K,V](pairs.toList.distinct)
def empty[K,V] = new ListMap[K,V](Nil)
private def remove[K,V](backing: List[(K,V)], k: K) = backing.filter(_._1 != k)
}
diff --git a/launch/Locks.scala b/launch/Locks.scala
index 21aedf934..eb4ced7b6 100644
--- a/launch/Locks.scala
+++ b/launch/Locks.scala
@@ -6,6 +6,7 @@ package xsbt.boot
import java.io.{File, FileOutputStream}
import java.nio.channels.FileChannel
import java.util.concurrent.Callable
+import scala.collection.immutable.List
object GetLocks
{
diff --git a/launch/Pre.scala b/launch/Pre.scala
index f08ead48d..b6c43ac90 100644
--- a/launch/Pre.scala
+++ b/launch/Pre.scala
@@ -2,6 +2,7 @@
* Copyright 2008, 2009, 2010 Mark Harrah
*/
package xsbt.boot
+import scala.collection.immutable.List
object Pre
{
@@ -19,7 +20,7 @@ object Pre
def declined(msg: String): Nothing = throw new BootException(msg)
def prefixError(msg: String): String = "Error during sbt execution: " + msg
def toBoolean(s: String) = java.lang.Boolean.parseBoolean(s)
- def toArray[T](list: List[T]) =
+ def toArray[T : ClassManifest](list: List[T]) =
{
val arr = new Array[T](list.length)
def copy(i: Int, rem: List[T]): Unit =
diff --git a/launch/Update.scala b/launch/Update.scala
index 41aab12c7..fb1663ca9 100644
--- a/launch/Update.scala
+++ b/launch/Update.scala
@@ -309,7 +309,7 @@ import SbtIvyLogger.{acceptError, acceptMessage}
/** A custom logger for Ivy to ignore the messages about not finding classes
* intentionally filtered using proguard and about 'unknown resolver'. */
-private final class SbtIvyLogger(logWriter: PrintWriter) extends DefaultMessageLogger(Message.MSG_INFO) with NotNull
+private final class SbtIvyLogger(logWriter: PrintWriter) extends DefaultMessageLogger(Message.MSG_INFO)
{
override def log(msg: String, level: Int)
{
diff --git a/launch/src/test/scala/ListMapTest.scala b/launch/src/test/scala/ListMapTest.scala
index ff867101a..820371c69 100644
--- a/launch/src/test/scala/ListMapTest.scala
+++ b/launch/src/test/scala/ListMapTest.scala
@@ -35,5 +35,4 @@ object ListMapEmpty extends Properties("ListMap.empty")
property("toSeq.isEmpty") = empty.toSeq.isEmpty
property("toStream.isEmpty") = empty.toStream.isEmpty
property("keys.isEmpty") = empty.keys.isEmpty
- property("elements.isEmpty") = !empty.elements.hasNext
}
\ No newline at end of file
diff --git a/launch/src/test/scala/LocksTest.scala b/launch/src/test/scala/LocksTest.scala
index 16fc93bcf..e6ad95896 100644
--- a/launch/src/test/scala/LocksTest.scala
+++ b/launch/src/test/scala/LocksTest.scala
@@ -3,20 +3,21 @@ package xsbt.boot
import org.scalacheck._
import Prop._
import java.io.File
+import sbt.IO.withTemporaryDirectory
/** These mainly test that things work in the uncontested case and that no OverlappingFileLockExceptions occur.
* There is no real locking testing, just the coordination of locking.*/
object LocksTest extends Properties("Locks")
{
property("Lock in nonexisting directory") = spec {
- FileUtilities.withTemporaryDirectory { dir =>
+ withTemporaryDirectory { dir =>
val lockFile = new File(dir, "doesntexist/lock")
Locks(lockFile, callTrue)
}
}
property("Uncontested re-entrant lock") = spec {
- FileUtilities.withTemporaryDirectory { dir =>
+ withTemporaryDirectory { dir =>
val lockFile = new File(dir, "lock")
Locks(lockFile, callLocked(lockFile)) &&
Locks(lockFile, callLocked(lockFile))
@@ -24,7 +25,7 @@ object LocksTest extends Properties("Locks")
}
property("Uncontested double lock") = spec {
- FileUtilities.withTemporaryDirectory { dir =>
+ withTemporaryDirectory { dir =>
val lockFileA = new File(dir, "lockA")
val lockFileB = new File(dir, "lockB")
Locks(lockFileA, callLocked(lockFileB)) &&
@@ -33,7 +34,7 @@ object LocksTest extends Properties("Locks")
}
property("Contested single lock") = spec {
- FileUtilities.withTemporaryDirectory { dir =>
+ withTemporaryDirectory { dir =>
val lockFile = new File(dir, "lock")
forkFold(2000){i => Locks(lockFile, callTrue) }
}
diff --git a/launch/src/test/scala/ScalaProviderTest.scala b/launch/src/test/scala/ScalaProviderTest.scala
index c15084aee..076f8cce2 100644
--- a/launch/src/test/scala/ScalaProviderTest.scala
+++ b/launch/src/test/scala/ScalaProviderTest.scala
@@ -5,6 +5,7 @@ import java.util.Properties
import xsbti._
import org.specs._
import LaunchTest._
+import sbt.IO.{createDirectory, touch,withTemporaryDirectory}
object ScalaProviderTest extends Specification
{
@@ -34,7 +35,7 @@ object ScalaProviderTest extends Specification
def checkLoad(arguments: List[String], mainClassName: String): MainResult =
checkLoad(arguments, mainClassName, _ => Array[File]())
def checkLoad(arguments: List[String], mainClassName: String, extra: File => Array[File]): MainResult =
- FileUtilities.withTemporaryDirectory { currentDirectory =>
+ withTemporaryDirectory { currentDirectory =>
withLauncher { launcher =>
Launch.run(launcher)(
new RunConfiguration(mapScalaVersion(LaunchTest.getScalaVersion), LaunchTest.testApp(mainClassName, extra(currentDirectory)).toID, currentDirectory, arguments)
@@ -45,8 +46,8 @@ object ScalaProviderTest extends Specification
private def createExtra(currentDirectory: File) =
{
val resourceDirectory = new File(currentDirectory, "resources")
- FileUtilities.createDirectory(resourceDirectory)
- testResources.foreach(resource => FileUtilities.touch(new File(resourceDirectory, resource.replace('/', File.separatorChar))))
+ createDirectory(resourceDirectory)
+ testResources.foreach(resource => touch(new File(resourceDirectory, resource.replace('/', File.separatorChar))))
Array(resourceDirectory)
}
private def checkScalaLoader(version: String): Unit = withLauncher( checkLauncher(version, scalaVersionMap(version)) )
@@ -67,7 +68,7 @@ object LaunchTest
import Repository.Predefined._
def testRepositories = List(Local, ScalaToolsReleases, ScalaToolsSnapshots).map(Repository.Predefined.apply)
def withLauncher[T](f: xsbti.Launcher => T): T =
- FileUtilities.withTemporaryDirectory { bootDirectory =>
+ withTemporaryDirectory { bootDirectory =>
f(Launcher(bootDirectory, testRepositories))
}
diff --git a/notes b/notes
index 5f336d8e4..83d6d29f9 100644
--- a/notes
+++ b/notes
@@ -1,3 +1,13 @@
+Issues moving Launcher to 2.8:
+ creating an Array requires a Manifest, which brings in 40k of classes in scala.reflect
+ scala.package$ is 3k (import scala.collection.immutable.List) and brings in scala.xml
+ RichInt 2k. scala.collection.mutable.StringBuilder.ensureCapacity uses it (max), which is needed for string concat
+ scala.xml brings in 50k of classes
+ scala.math brought in 30k, can't remove because RichInt apparently uses it
+ 100k additional size adds 50ms to startup time (on my faster machine)
+ difference between classpaths a) just launcher jar b) current directory + launcher jar is that b) is 50 ms slower than a)
+ was able to return to old size by enabling optimize/obfuscate phases of ProGuard
+
- script tasks (in 'scripts' branch). To use:
1) add implementation of jsr223 to project/build/lib, declare in project/plugins, or add to sbt startup classpath
2) Mix sbt.scripts.Scripts into your project definition
diff --git a/project/build/LauncherProguard.scala b/project/build/LauncherProguard.scala
index 60dd97431..17c6eeef3 100644
--- a/project/build/LauncherProguard.scala
+++ b/project/build/LauncherProguard.scala
@@ -3,20 +3,27 @@ import java.io.File
trait ProguardLaunch extends ProguardProject
{
+ override def optimize = 2
override def basicOptions = super.basicOptions ++ Seq(keepJLine)
def outputJar = rootProject.outputPath / ("sbt-launch-" + version + ".jar")
- override def keepClasses =
+ override def keepFullClasses =
+ "xsbti.**" ::
+ "jline.**" ::
+ Nil
+ override def keepClasses =
"org.apache.ivy.plugins.resolver.URLResolver" ::
"org.apache.ivy.plugins.resolver.IBiblioResolver" ::
- "xsbti.**" ::
Nil
+
override def mapInJars(inJars: Seq[File]) =
{
val inputJar = jarPath.asFile.getAbsolutePath
val jlineJars = runClasspath.getFiles.filter(isJLineJar)
// pull out Ivy in order to exclude resources inside
val (ivyJars, notIvy) = inJars.filter(jar => !isJLineJar(jar)).partition(isIvyJar)
- val otherJars = notIvy.filter(jar => !isJarX(jar, "scala-compiler"))
+ val (libraryJar, remaining) = notIvy.partition(isScalaJar)
+
+ val otherJars = remaining.filter(jar => !isJarX(jar, "scala-compiler"))
log.debug("proguard configuration:")
log.debug("\tJLline jar location: " + jlineJars.mkString(", "))
@@ -24,8 +31,9 @@ trait ProguardLaunch extends ProguardProject
log.debug("\tOther jars:\n\t" + otherJars.mkString("\n\t"))
val excludeIvyResourcesString = excludeString(excludeIvyResources)
((withJar(ivyJars.toSeq, "Ivy") + excludeIvyResourcesString) ::
- (withJar(jlineJars, "JLine") + "(!META-INF/**)" ) ::
- otherJars.map(jar => mkpath(jar) + "(!META-INF/**,!*.properties)").toList) map { "-injars " + _ }
+ (withJar(jlineJars, "JLine") + jlineFilter ) ::
+ (withJar(libraryJar, "Scala library") + libraryFilter) ::
+ otherJars.map(jar => mkpath(jar) + generalFilter).toList) map { "-injars " + _ }
}
private def excludeString(s: List[String]) = s.map("!" + _).mkString("(",",",")")
@@ -41,9 +49,14 @@ trait ProguardLaunch extends ProguardProject
"org/apache/ivy/plugins/report/ivy-report-*" ::
Nil
+ private def libraryFilter = "(!META-INF/**,!*.properties,!scala/actors/**.!scala/util/parsing/*.class,!scala/xml/**.class,!scala/package$.class,**.class)"
+ private def jlineFilter = "(!META-INF/**)"
+ private def generalFilter = "(!META-INF/**,!*.properties)"
+
private def withJar[T](files: Iterable[File], name: String) = mkpath(files.toSeq.firstOption.getOrElse(error(name + " not present (try running update)")))
private def isJLineJar(file: File) = isJarX(file, "jline")
private def isIvyJar(file: File) = isJarX(file, "ivy")
+ private def isScalaJar(file: File) = isJarX(file, "scala-library")
private def isJarX(file: File, x: String) =
{
val name = file.getName
diff --git a/project/build/ProguardProject.scala b/project/build/ProguardProject.scala
index b39661b1d..b9cd9145d 100644
--- a/project/build/ProguardProject.scala
+++ b/project/build/ProguardProject.scala
@@ -18,7 +18,7 @@ trait ProguardProject extends BasicScalaProject
def rootProjectDirectory = rootProject.info.projectPath
val toolsConfig = config("tools") hide
- val proguardJar = "net.sf.proguard" % "proguard" % "4.3" % "tools"
+ val proguardJar = "net.sf.proguard" % "proguard" % "4.4" % "tools"
lazy val proguard = proguardAction
def proguardAction = proguardTask dependsOn(writeProguardConfiguration) describedAs(ProguardDescription)
@@ -27,12 +27,17 @@ trait ProguardProject extends BasicScalaProject
def basicOptions: Seq[String] =
Seq(
- "-dontoptimize",
- "-dontobfuscate",
+ "-keep,allowoptimization,allowshrinking class * { *; }",
+ "-keepattributes SourceFile,LineNumberTable",
"-dontnote",
"-dontwarn",
- "-ignorewarnings")
+ "-ignorewarnings") ++
+ optimizeOptions
+
+ def keepFullClasses: Seq[String] = Nil
def keepClasses: Seq[String] = Nil
+ def optimize: Int = 0
+ def optimizeOptions = if(optimize <= 0) Seq("-dontoptimize") else Seq( "-optimizationpasses 2", "-optimizations !code/allocation/variable")
def mapInJars(inJars: Seq[File]): Seq[String] = inJars.map(f => "-injars " + mkpath(f))
def mapLibraryJars(libraryJars: Seq[File]): Seq[String] = libraryJars.map(f => "-libraryjars " + mkpath(f))
@@ -47,7 +52,8 @@ trait ProguardProject extends BasicScalaProject
val lines =
options ++
- keepClasses.map("-keep public class " + _ + " {\n public * ;\n}") ++
+ keepFullClasses.map("-keep public class " + _ + " {\n public protected * ;\n}") ++
+ keepClasses.map("-keep class " + _ + " {}") ++
mapInJars(inJars) ++
Seq("-injars " + mkpath(rawJarPath.asFile),
mapOutJar(outJar)) ++
diff --git a/project/build/XSbt.scala b/project/build/XSbt.scala
index bca223f91..d1ecb133a 100644
--- a/project/build/XSbt.scala
+++ b/project/build/XSbt.scala
@@ -113,7 +113,7 @@ class XSbt(info: ProjectInfo) extends ParentProject(info) with NoCrossPaths
{
override def scratch = true
override def consoleClasspath = testClasspath
- override def compileOptions = super.compileOptions ++ compileOptions("-Xelide-below", "3000")
+ override def compileOptions = super.compileOptions ++ compileOptions("-Xelide-below", "0")
}
trait Licensed extends BasicScalaProject
{
@@ -128,7 +128,6 @@ class XSbt(info: ProjectInfo) extends ParentProject(info) with NoCrossPaths
{
override def testCompileAction = super.testCompileAction dependsOn(compileInterfaceSub.`package`, interfaceSub.`package`)
override def testClasspath = super.testClasspath +++ compileInterfaceSub.packageSrcJar +++ interfaceSub.jarPath --- compilerInterfaceClasspath --- interfaceSub.mainCompilePath
- override def compileOptions = super.compileOptions ++ Seq(CompileOption("-Xno-varargs-conversion")) //needed for invoking nsc.scala.tools.Main.process(Array[String])
}
class IvyProject(info: ProjectInfo) extends Base(info) with TestWithIO with TestWithLog with TestWithLaunch
{
@@ -240,4 +239,4 @@ class XSbt(info: ProjectInfo) extends ParentProject(info) with NoCrossPaths
override def testCompileAction = super.testCompileAction dependsOn((testWithTestClasspath.map(_.testCompile) ++ testWithCompileClasspath.map(_.compile)) : _*)
override def testClasspath = (super.testClasspath /: (testWithTestClasspath.map(_.testClasspath) ++ testWithCompileClasspath.map(_.compileClasspath) ))(_ +++ _)
}
-}
\ No newline at end of file
+}
diff --git a/util/io/IO.scala b/util/io/IO.scala
index 7113e7aea..526f2ed67 100644
--- a/util/io/IO.scala
+++ b/util/io/IO.scala
@@ -68,7 +68,7 @@ object IO
(name, "")
}
- def touch(files: Iterable[File]): Unit = files.foreach(touch)
+ def touch(files: Traversable[File]): Unit = files.foreach(touch)
/** Creates a file at the given location.*/
def touch(file: File)
{
@@ -79,7 +79,7 @@ object IO
else if(!file.setLastModified(System.currentTimeMillis))
error("Could not update last modified time for file " + file)
}
- def createDirectories(dirs: Iterable[File]): Unit =
+ def createDirectories(dirs: Traversable[File]): Unit =
dirs.foreach(createDirectory)
def createDirectory(dir: File): Unit =
{
@@ -262,12 +262,12 @@ object IO
* @param sources The files to include in the jar file paired with the entry name in the jar.
* @param outputJar The file to write the jar to.
* @param manifest The manifest for the jar.*/
- def jar(sources: Iterable[(File,String)], outputJar: File, manifest: Manifest): Unit =
+ def jar(sources: Traversable[(File,String)], outputJar: File, manifest: Manifest): Unit =
archive(sources.toSeq, outputJar, Some(manifest))
/** Creates a zip file.
* @param sources The files to include in the zip file paired with the entry name in the zip.
* @param outputZip The file to write the zip to.*/
- def zip(sources: Iterable[(File,String)], outputZip: File): Unit =
+ def zip(sources: Traversable[(File,String)], outputZip: File): Unit =
archive(sources.toSeq, outputZip, None)
private def archive(sources: Seq[(File,String)], outputFile: File, manifest: Option[Manifest])
@@ -360,7 +360,7 @@ object IO
else
None
}
- def copy(sources: Iterable[(File,File)], overwrite: Boolean = false, preserveLastModified: Boolean = false): Set[File] =
+ def copy(sources: Traversable[(File,File)], overwrite: Boolean = false, preserveLastModified: Boolean = false): Set[File] =
sources.map( tupled(copyImpl(overwrite, preserveLastModified)) ).toSet
private def copyImpl(overwrite: Boolean, preserveLastModified: Boolean)(from: File, to: File): File =
{
@@ -469,7 +469,7 @@ object IO
for( (file, index) <- files.zipWithIndex) yield
(file, new File(dir, index.toHexString))
- def move(files: Iterable[(File, File)]): Unit =
+ def move(files: Traversable[(File, File)]): Unit =
files.foreach(Function.tupled(move))
def move(a: File, b: File): Unit =
diff --git a/util/io/Path.scala b/util/io/Path.scala
index c2b5e4e64..207ce1203 100644
--- a/util/io/Path.scala
+++ b/util/io/Path.scala
@@ -131,6 +131,8 @@ object Path extends Alternatives with Mapper
implicit def pathToFile(path: Path): File = path.asFile
implicit def pathsToFiles[CC[X] <: TraversableLike[X,CC[X]]](cc: CC[Path])(implicit cb: generic.CanBuildFrom[CC[Path], File, CC[File]]): CC[File] =
cc.map(_.asFile)
+ implicit def filesToFinder(cc: Traversable[File]): PathFinder = finder(cc)
+ implicit def pathsToFinder(cc: Traversable[Path]): PathFinder = lazyPathFinder(cc)
def fileProperty(name: String) = Path.fromFile(System.getProperty(name))
def userHome = fileProperty("user.home")
@@ -161,12 +163,12 @@ object Path extends Alternatives with Mapper
}
/** A PathFinder that selects the paths provided by the paths argument, which is
* reevaluated on each call to the PathFinder's get method. */
- def lazyPathFinder(paths: => Iterable[Path]): PathFinder =
+ def lazyPathFinder(paths: => Traversable[Path]): PathFinder =
new PathFinder
{
private[sbt] def addTo(pathSet: mutable.Set[Path]) = pathSet ++= paths
}
- def finder(files: => Iterable[File]): PathFinder = lazyPathFinder { fromFiles(files) }
+ def finder(files: => Traversable[File]): PathFinder = lazyPathFinder { fromFiles(files) }
/** The separator character of the platform.*/
val sep = java.io.File.separatorChar
@@ -244,7 +246,7 @@ object Path extends Alternatives with Mapper
}
def fromFile(file: String): Path = fromFile(new File(file))
def fromFile(file: File): Path = new FilePath(file)
- def fromFiles(files: Iterable[File]): Iterable[Path] = files.map(fromFile)
+ def fromFiles(files: Traversable[File]): Traversable[Path] = files.map(fromFile)
def getFiles(files: Traversable[Path]): immutable.Set[File] = files.map(_.asFile).toSet
def getURLs(files: Traversable[Path]): Array[URL] = files.map(_.asURL).toArray