diff options
author | Li Haoyi <haoyi.sg@gmail.com> | 2018-12-12 16:56:02 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-12 16:56:02 -0800 |
commit | 9ba4cb69331386dfde9bac69dc2d5b22401face3 (patch) | |
tree | 120349e8015ae5717d36bd44209cde6ff9543518 /scalalib/src/Lib.scala | |
parent | ea7fceb6e56f53bde3517586dfc57e10a605a524 (diff) | |
download | mill-9ba4cb69331386dfde9bac69dc2d5b22401face3.tar.gz mill-9ba4cb69331386dfde9bac69dc2d5b22401face3.tar.bz2 mill-9ba4cb69331386dfde9bac69dc2d5b22401face3.zip |
collapse boilerplate folder structure within src/ folders (#505)
* collapse boilerplate folder structure within src/ folders
* .
Diffstat (limited to 'scalalib/src/Lib.scala')
-rw-r--r-- | scalalib/src/Lib.scala | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/scalalib/src/Lib.scala b/scalalib/src/Lib.scala new file mode 100644 index 00000000..b8b253bd --- /dev/null +++ b/scalalib/src/Lib.scala @@ -0,0 +1,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) } + } + +} |