API: base types with applied type parameters

Compile task: fix detection of classpath changes
Aggressive compiler seems to work on scalaz now
This commit is contained in:
Mark Harrah 2010-01-23 09:33:42 -05:00
parent 5f9f3729d1
commit af288bb199
4 changed files with 37 additions and 7 deletions

View File

@ -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

View File

@ -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 =>

View File

@ -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))

View File

@ -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 =