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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
package mill
package scalalib
import java.io.{File, FileInputStream}
import java.lang.annotation.Annotation
import java.lang.reflect.Modifier
import java.util.zip.ZipInputStream
import javax.tools.ToolProvider
import ammonite.util.Util
import coursier.{Cache, Dependency, Fetch, Repository, Resolution}
import mill.scalalib.api.Util.isDotty
import mill.Agg
import mill.eval.{PathRef, Result}
import mill.modules.Jvm
import mill.api.Ctx
import sbt.testing._
import scala.collection.mutable
object Lib{
def depToDependencyJava(dep: Dep, platformSuffix: String = ""): Dependency = {
assert(dep.cross.isConstant, s"Not a Java dependency: $dep")
depToDependency(dep, "", platformSuffix)
}
def depToDependency(dep: Dep, scalaVersion: String, platformSuffix: String = ""): Dependency =
dep.toDependency(
binaryVersion = mill.scalalib.api.Util.scalaBinaryVersion(scalaVersion),
fullVersion = scalaVersion,
platformSuffix = platformSuffix
)
def resolveDependenciesMetadata(repositories: Seq[Repository],
depToDependency: Dep => coursier.Dependency,
deps: TraversableOnce[Dep],
mapDependencies: Option[Dependency => Dependency] = None) = {
val depSeq = deps.toSeq
mill.modules.Jvm.resolveDependenciesMetadata(
repositories,
depSeq.map(depToDependency),
depSeq.filter(_.force).map(depToDependency),
mapDependencies
)
}
/**
* Resolve dependencies using Coursier.
*
* We do not bother breaking this out into the separate ZincWorker classpath,
* because Coursier is already bundled with mill/Ammonite to support the
* `import $ivy` syntax.
*/
def resolveDependencies(repositories: Seq[Repository],
depToDependency: Dep => coursier.Dependency,
deps: TraversableOnce[Dep],
sources: Boolean = false,
mapDependencies: Option[Dependency => Dependency] = None): Result[Agg[PathRef]] = {
val depSeq = deps.toSeq
mill.modules.Jvm.resolveDependencies(
repositories,
depSeq.map(depToDependency),
depSeq.filter(_.force).map(depToDependency),
sources,
mapDependencies
)
}
def scalaCompilerIvyDeps(scalaOrganization: String, scalaVersion: String) =
if (mill.scalalib.api.Util.isDotty(scalaVersion))
Agg(ivy"$scalaOrganization::dotty-compiler:$scalaVersion".forceVersion())
else
Agg(
ivy"$scalaOrganization:scala-compiler:$scalaVersion".forceVersion(),
ivy"$scalaOrganization:scala-reflect:$scalaVersion".forceVersion()
)
def scalaRuntimeIvyDeps(scalaOrganization: String, scalaVersion: String) = Agg[Dep](
ivy"$scalaOrganization:scala-library:$scalaVersion".forceVersion()
)
def listClassFiles(base: os.Path): Iterator[String] = {
if (os.isDir(base)) os.walk(base).toIterator.filter(_.ext == "class").map(_.relativeTo(base).toString)
else {
val zip = new ZipInputStream(new FileInputStream(base.toIO))
Iterator.continually(zip.getNextEntry).takeWhile(_ != null).map(_.getName).filter(_.endsWith(".class"))
}
}
def discoverTests(cl: ClassLoader, framework: Framework, classpath: Agg[os.Path]) = {
val fingerprints = framework.fingerprints()
val testClasses = classpath.flatMap { base =>
// Don't blow up if there are no classfiles representing
// the tests to run Instead just don't run anything
if (!os.exists(base)) Nil
else listClassFiles(base).flatMap { path =>
val cls = cl.loadClass(path.stripSuffix(".class").replace('/', '.'))
val publicConstructorCount =
cls.getConstructors.count(c => c.getParameterCount == 0 && Modifier.isPublic(c.getModifiers))
if (Modifier.isAbstract(cls.getModifiers) || cls.isInterface || publicConstructorCount > 1) {
None
} else {
(cls.getName.endsWith("$"), publicConstructorCount == 0) match{
case (true, true) => matchFingerprints(cl, cls, fingerprints, isModule = true)
case (false, false) => matchFingerprints(cl, cls, fingerprints, isModule = false)
case _ => None
}
}
}
}
testClasses
}
def matchFingerprints(cl: ClassLoader, cls: Class[_], fingerprints: Array[Fingerprint], isModule: Boolean) = {
fingerprints.find {
case f: SubclassFingerprint =>
f.isModule == isModule &&
cl.loadClass(f.superclassName()).isAssignableFrom(cls)
case f: AnnotatedFingerprint =>
val annotationCls = cl.loadClass(f.annotationName()).asInstanceOf[Class[Annotation]]
f.isModule == isModule &&
(
cls.isAnnotationPresent(annotationCls) ||
cls.getDeclaredMethods.exists(_.isAnnotationPresent(annotationCls))
)
}.map { f => (cls, f) }
}
}
|