mirror of https://github.com/sbt/sbt.git
Desugar case class IncOptions in binary compatible way.
Expand case class `IncOptions` in binary compatible way so we can have
better control of methods like `unapply` when new fields are added.
Great precaution has been taken to ensure that this commit doesn't break
binary compatibility. I took a dump of javap output before and after
this change for both the class and it's companion object.
The diff is presented below:
diff -u ~/inc-options-before ~/inc-options-after
--- /Users/grek/inc-options-before 2013-11-03 14:48:45.000000000 +0100
+++ /Users/grek/inc-options-after 2013-11-03 15:53:10.000000000 +0100
@@ -9,7 +9,11 @@
public static java.lang.String transitiveStepKey();
public static sbt.inc.IncOptions setTransactional(sbt.inc.IncOptions, java.io.File);
public static sbt.inc.IncOptions defaultTransactional(java.io.File);
+ public static scala.Option unapply(sbt.inc.IncOptions);
+ public static sbt.inc.IncOptions apply(int, double, boolean, boolean, int, scala.Option, scala.Function0);
public static sbt.inc.IncOptions Default();
+ public static scala.Function1 tupled();
+ public static scala.Function1 curried();
public int transitiveStep();
public double recompileAllFraction();
public boolean relationsDebug();
diff -u inc-options-module-before inc-options-module-after
--- inc-options-module-before 2013-11-03 14:48:55.000000000 +0100
+++ inc-options-module-after 2013-11-12 21:00:41.000000000 +0100
@@ -3,6 +3,9 @@
public static final sbt.inc.IncOptions$ MODULE$;
public static {};
public sbt.inc.IncOptions Default();
+ public final java.lang.String toString();
+ public sbt.inc.IncOptions apply(int, double, boolean, boolean, int, scala.Option, scala.Function0);
+ public scala.Option unapply(sbt.inc.IncOptions);
public sbt.inc.IncOptions defaultTransactional(java.io.File);
public sbt.inc.IncOptions setTransactional(sbt.inc.IncOptions, java.io.File);
public java.lang.String transitiveStepKey();
@@ -13,7 +16,5 @@
public java.lang.String apiDiffContextSize();
public sbt.inc.IncOptions fromStringMap(java.util.Map);
public java.util.Map toStringMap(sbt.inc.IncOptions);
- public sbt.inc.IncOptions apply(int, double, boolean, boolean, int, scala.Option, scala.Function0);
- public scala.Option unapply(sbt.inc.IncOptions);
}
The first diff shows that there are just more static forwarders defined
for top-level companion object and that is binary compatible change.
The second diff shows that there are just a few minor differences in
order in which `unapply`, `apply` and bridge method for `apply` are
defined. Also, there's a new `toString` declaration. All those changes are
binary compatible.
All methods that are generated for a case class are marked as deprecated
and will be removed in the future.
This commit is contained in:
parent
f2bdeff486
commit
b77b0e161e
|
|
@ -5,10 +5,15 @@ package sbt.inc
|
|||
/**
|
||||
* Represents all configuration options for the incremental compiler itself and
|
||||
* not the underlying Java/Scala compiler.
|
||||
*
|
||||
* NOTE: This class used to be a case class but due to problems with retaining
|
||||
* binary compatibility while new fields are added it has been expanded to a
|
||||
* regular class. All compiler-generated methods for a case class has been
|
||||
* defined explicitly.
|
||||
*/
|
||||
final case class IncOptions(
|
||||
final class IncOptions(
|
||||
/** After which step include whole transitive closure of invalidated source files. */
|
||||
transitiveStep: Int,
|
||||
val transitiveStep: Int,
|
||||
/**
|
||||
* What's the fraction of invalidated source files when we switch to recompiling
|
||||
* all files and giving up incremental compilation altogether. That's useful in
|
||||
|
|
@ -16,9 +21,9 @@ final case class IncOptions(
|
|||
* in multiple steps is high. Multi-step incremental recompilation is slower
|
||||
* than recompiling everything in one step.
|
||||
*/
|
||||
recompileAllFraction: Double,
|
||||
val recompileAllFraction: Double,
|
||||
/** Print very detailed information about relations, such as dependencies between source files. */
|
||||
relationsDebug: Boolean,
|
||||
val relationsDebug: Boolean,
|
||||
/**
|
||||
* Enable tools for debugging API changes. At the moment this option is unused but in the
|
||||
* future it will enable for example:
|
||||
|
|
@ -26,26 +31,88 @@ final case class IncOptions(
|
|||
* - diffing textual API representation which helps understanding what kind of changes
|
||||
* to APIs are visible to the incremental compiler
|
||||
*/
|
||||
apiDebug: Boolean,
|
||||
val apiDebug: Boolean,
|
||||
/**
|
||||
* Controls context size (in lines) displayed when diffs are produced for textual API
|
||||
* representation.
|
||||
*
|
||||
* This option is used only when `apiDebug == true`.
|
||||
*/
|
||||
apiDiffContextSize: Int,
|
||||
val apiDiffContextSize: Int,
|
||||
/**
|
||||
* The directory where we dump textual representation of APIs. This method might be called
|
||||
* only if apiDebug returns true. This is unused option at the moment as the needed functionality
|
||||
* is not implemented yet.
|
||||
*/
|
||||
apiDumpDirectory: Option[java.io.File],
|
||||
val apiDumpDirectory: Option[java.io.File],
|
||||
/** Creates a new ClassfileManager that will handle class file deletion and addition during a single incremental compilation run. */
|
||||
newClassfileManager: () => ClassfileManager
|
||||
)
|
||||
val newClassfileManager: () => ClassfileManager
|
||||
) extends Product with Serializable {
|
||||
|
||||
object IncOptions {
|
||||
val Default = IncOptions(
|
||||
//- EXPANDED CASE CLASS METHOD BEGIN -//
|
||||
@deprecated("Methods generated for case class will be removed in the future.", "0.13.2")
|
||||
def copy(transitiveStep: Int = this.transitiveStep, recompileAllFraction: Double = this.recompileAllFraction,
|
||||
relationsDebug: Boolean = this.relationsDebug, apiDebug: Boolean = this.apiDebug,
|
||||
apiDiffContextSize: Int = this.apiDiffContextSize,
|
||||
apiDumpDirectory: Option[java.io.File] = this.apiDumpDirectory,
|
||||
newClassfileManager: () => ClassfileManager = this.newClassfileManager): IncOptions = {
|
||||
new IncOptions(transitiveStep, recompileAllFraction, relationsDebug, apiDebug, apiDiffContextSize,
|
||||
apiDumpDirectory, newClassfileManager)
|
||||
}
|
||||
|
||||
@deprecated("Methods generated for case class will be removed in the future.", "0.13.2")
|
||||
override def productPrefix: String = "IncOptions"
|
||||
|
||||
@deprecated("Methods generated for case class will be removed in the future.", "0.13.2")
|
||||
def productArity: Int = 7
|
||||
|
||||
@deprecated("Methods generated for case class will be removed in the future.", "0.13.2")
|
||||
def productElement(x$1: Int): Any = x$1 match {
|
||||
case 0 => IncOptions.this.transitiveStep
|
||||
case 1 => IncOptions.this.recompileAllFraction
|
||||
case 2 => IncOptions.this.relationsDebug
|
||||
case 3 => IncOptions.this.apiDebug
|
||||
case 4 => IncOptions.this.apiDiffContextSize
|
||||
case 5 => IncOptions.this.apiDumpDirectory
|
||||
case 6 => IncOptions.this.newClassfileManager
|
||||
case _ => throw new IndexOutOfBoundsException(x$1.toString())
|
||||
}
|
||||
|
||||
@deprecated("Methods generated for case class will be removed in the future.", "0.13.2")
|
||||
override def productIterator: Iterator[Any] = scala.runtime.ScalaRunTime.typedProductIterator[Any](IncOptions.this)
|
||||
|
||||
@deprecated("Methods generated for case class will be removed in the future.", "0.13.2")
|
||||
def canEqual(x$1: Any): Boolean = x$1.isInstanceOf[IncOptions]
|
||||
|
||||
override def hashCode(): Int = {
|
||||
import scala.runtime.Statics
|
||||
var acc: Int = -889275714
|
||||
acc = Statics.mix(acc, transitiveStep)
|
||||
acc = Statics.mix(acc, Statics.doubleHash(recompileAllFraction))
|
||||
acc = Statics.mix(acc, if (relationsDebug) 1231 else 1237)
|
||||
acc = Statics.mix(acc, if (apiDebug) 1231 else 1237)
|
||||
acc = Statics.mix(acc, apiDiffContextSize)
|
||||
acc = Statics.mix(acc, Statics.anyHash(apiDumpDirectory))
|
||||
acc = Statics.mix(acc, Statics.anyHash(newClassfileManager))
|
||||
Statics.finalizeHash(acc, 7)
|
||||
}
|
||||
|
||||
override def toString(): String = scala.runtime.ScalaRunTime._toString(IncOptions.this)
|
||||
|
||||
override def equals(x$1: Any): Boolean = {
|
||||
this.eq(x$1.asInstanceOf[Object]) || (x$1.isInstanceOf[IncOptions] && ({
|
||||
val IncOptions$1: IncOptions = x$1.asInstanceOf[IncOptions]
|
||||
transitiveStep == IncOptions$1.transitiveStep && recompileAllFraction == IncOptions$1.recompileAllFraction &&
|
||||
relationsDebug == IncOptions$1.relationsDebug && apiDebug == IncOptions$1.apiDebug &&
|
||||
apiDiffContextSize == IncOptions$1.apiDiffContextSize && apiDumpDirectory == IncOptions$1.apiDumpDirectory &&
|
||||
newClassfileManager == IncOptions$1.newClassfileManager
|
||||
}))
|
||||
}
|
||||
//- EXPANDED CASE CLASS METHOD END -//
|
||||
}
|
||||
|
||||
object IncOptions extends Serializable {
|
||||
val Default = new IncOptions(
|
||||
// 1. recompile changed sources
|
||||
// 2(3). recompile direct dependencies and transitive public inheritance dependencies of sources with API changes in 1(2).
|
||||
// 4. further changes invalidate all dependencies transitively to avoid too many steps
|
||||
|
|
@ -57,6 +124,25 @@ object IncOptions {
|
|||
apiDumpDirectory = None,
|
||||
newClassfileManager = ClassfileManager.deleteImmediately
|
||||
)
|
||||
//- EXPANDED CASE CLASS METHOD BEGIN -//
|
||||
final override def toString(): String = "IncOptions"
|
||||
def apply(transitiveStep: Int, recompileAllFraction: Double, relationsDebug: Boolean, apiDebug: Boolean,
|
||||
apiDiffContextSize: Int, apiDumpDirectory: Option[java.io.File],
|
||||
newClassfileManager: () => ClassfileManager): IncOptions = {
|
||||
new IncOptions(transitiveStep, recompileAllFraction, relationsDebug, apiDebug, apiDiffContextSize,
|
||||
apiDumpDirectory, newClassfileManager)
|
||||
}
|
||||
@deprecated("Methods generated for case class will be removed in the future.", "0.13.2")
|
||||
def unapply(x$0: IncOptions): Option[(Int, Double, Boolean, Boolean, Int, Option[java.io.File], () => AnyRef)] = {
|
||||
if (x$0 == null) None
|
||||
else Some.apply[(Int, Double, Boolean, Boolean, Int, Option[java.io.File], () => AnyRef)](
|
||||
Tuple7.apply[Int, Double, Boolean, Boolean, Int, Option[java.io.File], () => AnyRef](
|
||||
x$0.transitiveStep, x$0.recompileAllFraction, x$0.relationsDebug, x$0.apiDebug, x$0.apiDiffContextSize,
|
||||
x$0.apiDumpDirectory, x$0.newClassfileManager))
|
||||
}
|
||||
private def readResolve(): Object = IncOptions
|
||||
//- EXPANDED CASE CLASS METHOD END -//
|
||||
|
||||
def defaultTransactional(tempDir: File): IncOptions = setTransactional(Default, tempDir)
|
||||
def setTransactional(opts: IncOptions, tempDir: File): IncOptions =
|
||||
opts.copy(newClassfileManager = ClassfileManager.transactional(tempDir))
|
||||
|
|
@ -97,7 +183,7 @@ object IncOptions {
|
|||
else None
|
||||
}
|
||||
|
||||
IncOptions(getTransitiveStep, getRecompileAllFraction, getRelationsDebug, getApiDebug, getApiDiffContextSize,
|
||||
new IncOptions(getTransitiveStep, getRecompileAllFraction, getRelationsDebug, getApiDebug, getApiDiffContextSize,
|
||||
getApiDumpDirectory, ClassfileManager.deleteImmediately)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue