From af288bb199fb201dbb0b4d0729b0ada67e609cfb Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Sat, 23 Jan 2010 09:33:42 -0500 Subject: [PATCH] API: base types with applied type parameters Compile task: fix detection of classpath changes Aggressive compiler seems to work on scalaz now --- cache/tracking/Tracked.scala | 16 ++++++++++++++++ compile/api/SameAPI.scala | 1 - compile/interface/API.scala | 8 +++++++- tasks/standard/Compile.scala | 19 ++++++++++++++----- 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/cache/tracking/Tracked.scala b/cache/tracking/Tracked.scala index dc8c6095e..f79a2a7ee 100644 --- a/cache/tracking/Tracked.scala +++ b/cache/tracking/Tracked.scala @@ -16,6 +16,22 @@ trait Tracked extends NotNull /** Clears the cache. If also cleaning, 'clean' should be called first as it might require information from the cache.*/ def clear: Task[Unit] } +class Timestamp(val cacheFile: File) extends Tracked +{ + val clean = Clean(cacheFile) + def clear = Task.empty + def apply[T](f: Long => Task[T]): Task[T] = + { + val getTimestamp = Task { readTimestamp } + getTimestamp bind f map { result => + FileUtilities.write(cacheFile, System.currentTimeMillis.toString) + result + } + } + def readTimestamp: Long = + try { FileUtilities.read(cacheFile).toLong } + catch { case _: NumberFormatException | _: java.io.FileNotFoundException => 0 } +} object Clean { def apply(src: Task[Set[File]]): Task[Unit] = src map FileUtilities.delete diff --git a/compile/api/SameAPI.scala b/compile/api/SameAPI.scala index 70d01f78c..d944f4329 100644 --- a/compile/api/SameAPI.scala +++ b/compile/api/SameAPI.scala @@ -77,7 +77,6 @@ private class SameAPI(a: Source, b: Source) //println("Comparing \n\t" + show(a) + "\nagainst\n\t" + show(b)) def sameDefs(a: List[Definition], b: List[Definition]): Boolean = { - println("\t " + a.size + " to " + b.size + "") a match { case adef :: atail => diff --git a/compile/interface/API.scala b/compile/interface/API.scala index b7778b88f..13e6b1357 100644 --- a/compile/interface/API.scala +++ b/compile/interface/API.scala @@ -166,7 +166,13 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend { val s = info.typeSymbol val (declared, inherited) = info.members.partition(_.owner == s) - structure(info.baseClasses.map(_.tpe), declared, inherited) // linearization instead of parents + // would be nice to know how to do this properly: + // baseClasses contains symbols in proper linearization order, but tpe doesn't have type parameters applied + // baseTypeSeq contains the types with parameters properly applied + val bases = info.baseClasses.tail + val bs = info.baseTypeSeq.toList.tail + val baseTypes = bases.map(base => bs.find(_.typeSymbol eq base).get) + structure(baseTypes, declared, inherited) } private def structure(parents: List[Type], declared: List[Symbol], inherited: List[Symbol]): xsbti.api.Structure = new xsbti.api.Structure(types(parents), processDefinitions(declared), Array())//processDefinitions(inherited)) diff --git a/tasks/standard/Compile.scala b/tasks/standard/Compile.scala index bd5df77fd..3dcf01bc8 100644 --- a/tasks/standard/Compile.scala +++ b/tasks/standard/Compile.scala @@ -59,6 +59,7 @@ class AggressiveCompile(val cacheDirectory: File, val compilerTask: Task[Analyzi def apply(sourceChanges: ChangeReport[File], classpathChanges: ChangeReport[File], outputDirectory: File, options: Seq[String]): Task[Set[File]] = compilerTask bind { compiler => tracking { tracker => + timestamp { tstamp => Task { log.info("Removed sources: \n\t" + sourceChanges.removed.mkString("\n\t")) log.info("Added sources: \n\t" + sourceChanges.added.mkString("\n\t")) @@ -68,22 +69,29 @@ class AggressiveCompile(val cacheDirectory: File, val compilerTask: Task[Analyzi val readTracker = tracker.read // directories that are no longer on the classpath, not necessarily removed from the filesystem val removedDirectories = classpathChanges.removed.filter(_.isDirectory) + log.info("Directories no longer on classpath:\n\t" + removedDirectories.mkString("\n\t")) - def uptodate(time: Long, files: Iterable[File]) = files.forall(_.lastModified <= time) + def uptodate(time: Long, files: Iterable[File]) = files.forall(_.lastModified < time) def isOutofdate(file: File, related: => Iterable[File]) = !file.exists || !uptodate(file.lastModified, related) + def invalidatesUses(file: File) = !file.exists || file.lastModified > tstamp def isProductOutofdate(product: File) = isOutofdate(product, readTracker.sources(product)) def inRemovedDirectory(file: File) = removedDirectories.exists(dir => FileUtilities.relativize(dir, file).isDefined) - def isUsedOutofdate(file: File) = classpathChanges.modified(file) || inRemovedDirectory(file) || isOutofdate(file, readTracker.usedBy(file)) + def isUsedOutofdate(file: File) = classpathChanges.modified(file) || inRemovedDirectory(file) || invalidatesUses(file) // these are products that no longer exist or are older than the sources that produced them val outofdateProducts = readTracker.allProducts.filter(isProductOutofdate) + log.info("Out of date products:\n\t" + outofdateProducts.mkString("\n\t")) // used classes and jars that a) no longer exist b) are no longer on the classpath or c) are newer than the sources that use them val outofdateUses = readTracker.allUsed.filter(isUsedOutofdate) + log.info("Out of date binaries:\n\t" + outofdateUses.mkString("\n\t")) val modifiedSources = sourceChanges.modified val invalidatedByClasspath = outofdateUses.flatMap(readTracker.usedBy) + log.info("Invalidated by classpath changes:\n\t" + invalidatedByClasspath.mkString("\n\t")) val invalidatedByRemovedSrc = sourceChanges.removed.flatMap(readTracker.dependsOn) + log.info("Invalidated by removed sources:\n\t" + invalidatedByRemovedSrc.mkString("\n\t")) val productsOutofdate = outofdateProducts.flatMap(readTracker.sources) + log.info("Invalidated by out of date products:\n\t" + productsOutofdate.mkString("\n\t")) val rawInvalidatedSources = modifiedSources ++ invalidatedByClasspath ++ invalidatedByRemovedSrc ++ productsOutofdate val invalidatedSources = scc(readTracker, rawInvalidatedSources) @@ -96,7 +104,7 @@ class AggressiveCompile(val cacheDirectory: File, val compilerTask: Task[Analyzi tracker.pending(sources) FileUtilities.delete(invalidatedProducts) - log.info("Initially invalidated sources:\n\t" + sources.mkString("\n\t")) + log.info("All initially invalidated sources:\n\t" + sources.mkString("\n\t")) if(!sources.isEmpty) { val newAPIMap = doCompile(sources, classpath, outputDirectory, options, tracker, compiler, log) @@ -115,7 +123,7 @@ class AggressiveCompile(val cacheDirectory: File, val compilerTask: Task[Analyzi } Set() ++ tracker.read.allProducts } - } + }} } def products(tracker: ReadTracking[File], srcs: Set[File]): Set[File] = srcs.flatMap(tracker.products) @@ -129,7 +137,8 @@ class AggressiveCompile(val cacheDirectory: File, val compilerTask: Task[Analyzi import sbinary.DefaultProtocol.FileFormat val tracking = new DependencyTracked(cacheDirectory, true, (files: File) => FileUtilities.delete(files)) - def tracked = Seq(tracking) + val timestamp = new Timestamp(new File(cacheDirectory,"timestamp")) + def tracked = Seq(tracking, timestamp) def sameAPI[T](a: scala.collection.Map[T, Source], b: scala.collection.Map[T, Source], t: T): Boolean = sameAPI(a.get(t), b.get(t)) def sameAPI(a: Option[Source], b: Option[Source]): Boolean =