sbt.inc.Changes.scala Maven / Gradle / Ivy
/* sbt -- Simple Build Tool
* Copyright 2010 Mark Harrah
*/
package sbt
package inc
import xsbt.api.NameChanges
import java.io.File
import xsbti.api.{ _internalOnly_NameHashes => NameHashes }
import xsbti.api.{ _internalOnly_NameHash => NameHash }
final case class InitialChanges(internalSrc: Changes[File], removedProducts: Set[File], binaryDeps: Set[File], external: APIChanges[String])
final class APIChanges[T](val apiChanges: Iterable[APIChange[T]]) {
override def toString = "API Changes: " + apiChanges
def allModified: Iterable[T] = apiChanges.map(_.modified)
}
sealed abstract class APIChange[T](val modified: T)
/**
* If we recompile a source file that contains a macro definition then we always assume that it's
* api has changed. The reason is that there's no way to determine if changes to macros implementation
* are affecting its users or not. Therefore we err on the side of caution.
*/
final case class APIChangeDueToMacroDefinition[T](modified0: T) extends APIChange(modified0)
final case class SourceAPIChange[T](modified0: T) extends APIChange(modified0)
/**
* An APIChange that carries information about modified names.
*
* This class is used only when name hashing algorithm is enabled.
*/
final case class NamesChange[T](modified0: T, modifiedNames: ModifiedNames) extends APIChange(modified0)
/**
* ModifiedNames are determined by comparing name hashes in two versions of an API representation.
*
* Note that we distinguish between sets of regular (non-implicit) and implicit modified names.
* This distinction is needed because the name hashing algorithm makes different decisions based
* on whether modified name is implicit or not. Implicit names are much more difficult to handle
* due to difficulty of reasoning about the implicit scope.
*/
final case class ModifiedNames(regularNames: Set[String], implicitNames: Set[String]) {
override def toString: String =
s"ModifiedNames(regularNames = ${regularNames mkString ", "}, implicitNames = ${implicitNames mkString ", "})"
}
object ModifiedNames {
def compareTwoNameHashes(a: NameHashes, b: NameHashes): ModifiedNames = {
val modifiedRegularNames = calculateModifiedNames(a.regularMembers.toSet, b.regularMembers.toSet)
val modifiedImplicitNames = calculateModifiedNames(a.implicitMembers.toSet, b.implicitMembers.toSet)
ModifiedNames(modifiedRegularNames, modifiedImplicitNames)
}
private def calculateModifiedNames(xs: Set[NameHash], ys: Set[NameHash]): Set[String] = {
val differentNameHashes = (xs union ys) diff (xs intersect ys)
differentNameHashes.map(_.name)
}
}
trait Changes[A] {
def added: Set[A]
def removed: Set[A]
def changed: Set[A]
def unmodified: Set[A]
}
sealed abstract class Change(val file: File)
final class Removed(f: File) extends Change(f)
final class Added(f: File, newStamp: Stamp) extends Change(f)
final class Modified(f: File, oldStamp: Stamp, newStamp: Stamp) extends Change(f)