blob: 8d67be745fdd3708718244a698f0edb64448a1e6 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
package cbt
import cbt.eval.Eval
trait DynamicOverrides extends BaseBuild{
private val twitterEval = {
taskCache[DynamicOverrides]( "eval" ).memoize{
new Eval{
override lazy val impliedClassPath: List[String] = context.parentBuild.get.classpath.strings.toList//new ScalaCompilerDependency( context.cbtLastModified, context.paths.mavenCache, scalaVersion ).classpath.strings.toList
override def classLoader = DynamicOverrides.this.getClass.getClassLoader
}
}
}
protected [cbt] def overrides: String = ""
// TODO: add support for Build inner classes
import scala.reflect.runtime.universe._
def newBuild[T <: DynamicOverrides:TypeTag]: T = newBuild[T](context)("")
def newBuild[T <: DynamicOverrides:TypeTag](body: String): T = newBuild[T](context)(body)
def newBuild[T <: DynamicOverrides:TypeTag](context: Context)(body: String): T = {
val tag = typeTag[T]
val mixinClass = tag.mirror.runtimeClass(tag.tpe)
assert(mixinClass.getTypeParameters.size == 0)
val mixin = if(
mixinClass == classOf[Nothing]
|| mixinClass.getSimpleName == "Build"
) "" else " with "+mixinClass.getName
import scala.collection.JavaConverters._
val parent = Option(
if(this.getClass.getName.startsWith("Evaluator__"))
this.getClass.getName.dropWhile(_ != '$').drop(1).stripSuffix("$1")
else
this.getClass.getName
).getOrElse(
throw new Exception( "You cannot have more than one newBuild call on the Stack right now." )
)
val overrides = "" // currently disables, but can be used to force overrides everywhere
if(mixin == "" && overrides == "" && body == ""){
// TODO: is it possible for the contructor to have the wrong signature and
// thereby produce a pretty hard to understand error message here?
this.getClass
.getConstructor(classOf[Context])
.newInstance(context)
.asInstanceOf[T]
} else {
val baseName = "DynamicBuild" + System.currentTimeMillis
val overrideName = baseName+"Overrides"
val (finalName, code) = if(overrides == ""){
(
baseName,
s"""
class $baseName(context: _root_.cbt.Context)
extends $parent(context)$mixin{
$body
}
"""
)
} else {
(
overrideName,
s"""
class $baseName(context: _root_.cbt.Context)
extends $parent(context)$mixin{
$body
}
class $overrideName(context: _root_.cbt.Context)
extends $baseName(context){
$overrides
}
"""
)
}
logger.dynamic("Dynamically generated code:\n" ++ code)
twitterEval.compile(code)
val createBuild = twitterEval.apply[Context => T](s"new $finalName(_: _root_.cbt.Context)",false)
createBuild( context ).asInstanceOf[T]
}
}
def runFlat: ExitCode = newBuild[DynamicOverrides]{"""
override def flatClassLoader = true
"""}.run
}
|