Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

My variant of #466 #486

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
127 changes: 90 additions & 37 deletions examples/cross-rewrite-example/build/build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,65 @@ import scalafix.util._
import scalafix.util.TreePatch._
import scalafix.util.TokenPatch._

class Build(val context: Context) extends BaseBuild{ outer =>
override def defaultScalaVersion = "2.11.8"
class TestBuild( val context: Context, mainBuild: BaseBuild ) extends ScalaTest with Scalameta {
override def defaultScalaVersion = mainBuild.scalaVersion
override def projectDirectory = CrossRewrite.mkdirIfNotExists( mainBuild.projectDirectory / "test" )
override def dependencies = mainBuild +: super.dependencies
}

class Build(val context: Context) extends BaseBuild with Scalameta with PackageJars { defaultMainBuild =>
override def defaultScalaVersion: String = "2.12.1"
override def groupId = "org.cvogt"
override def artifactId = "cbt-examples-cross-rewrite"
override def version = "0.1"
override def scaladoc = None // Scalameta breaks Scaladoc

override def test: BaseBuild = new TestBuild( context, this )

def cross = for{
( v, version_rewrites ) <- CrossRewrite.versions
( label, dep, lib_rewrites ) <- CrossRewrite.libs
} yield {
new Build(context) with Scalafix{ patchedMainBuild =>
override def defaultScalaVersion = v
override def artifactId = super.artifactId ~ "-" ~ label
override def projectDirectory = CrossRewrite.mkdirIfNotExists(
defaultMainBuild.target / "rewrites" / label ++ "-" ++ v
)
override def dependencies =
super.dependencies ++ Resolver(mavenCentral).bind(
// hack because using ScalaDependency in the outer build binds it
// to THAT builds initial scalaVersion, which we are overriding
// here, but we are looping over libs outside of that, so
// the override doesn't affect it
// So we use MavenDependency instead and append the id here.
dep.copy(artifactId = dep.artifactId + "_" + scalaMajorVersion)
)
override def sources = CrossRewrite.patchesSources(
defaultMainBuild.sources,
projectDirectory / "src",
defaultMainBuild.classpath,
lib_rewrites ++ version_rewrites,
lib
)

override def test = new TestBuild( context, this ){
override def sources = CrossRewrite.patchesSources(
defaultMainBuild.test.sources,
projectDirectory / "src",
defaultMainBuild.test.classpath,
lib_rewrites ++ version_rewrites,
lib
)
}
}
}
}

object CrossRewrite{
def versions = Seq[(String, Seq[Patch])](
scalaVersion -> Seq(),
"2.12.1" -> Seq(
"2.12.1" -> Seq(),
"2.11.8" -> Seq(
RemoveGlobalImport(
importer"scala.concurrent.Future"
),
Expand All @@ -23,50 +76,50 @@ class Build(val context: Context) extends BaseBuild{ outer =>
def libs = Seq[(String, MavenDependency, Seq[Patch])](
(
"scalaz",
ScalaDependency( "org.scalaz", "scalaz-core", "7.2.2" ),
MavenDependency( "org.scalaz", "scalaz-core", "7.2.10" ),
Seq(
AddGlobalImport(importer"scalaz._"),
Replace(Symbol("_root_.scala.package.Either."), q"\/"),
Replace(Symbol("_root_.scala.util.Right."), q"\/-"),
RemoveGlobalImport(importer"cats.implicits._")
)
),
(
"cats",
ScalaDependency( "org.typelevel", "cats", "0.9.0" ),
MavenDependency( "org.typelevel", "cats", "0.9.0" ),
Seq(
AddGlobalImport(importer"cats.implicits._")
)
)
)

def cross = versions.flatMap{ case ( v, version_rewrites ) =>
libs.map{
case ( label, dep, lib_rewrites ) =>
val d = outer.target / "rewrites" / label ++ "-" ++ v
d.mkdirs
new Build(context) with Scalafix with PackageJars{
override def groupId = "org.cvogt"
override def artifactId = "cbt-examples-cross-rewrite-" + label
override def version = "0.1"
override def defaultScalaVersion = v
override def dependencies = super.dependencies ++ Resolver( mavenCentral ).bind( dep )
override def projectDirectory = d
override def scaladoc = None
override def sources = {
val fromTo = lib.autoRelative( outer.sources ).collect{
case (location, relative) if location.isFile
=> location -> projectDirectory / "src" / relative
}
def mkdirIfNotExists( d: File ): File = {
d.mkdirs
d
}

val to = fromTo.map(_._2)
assert( ( to diff to.distinct ).isEmpty )
def patchesSources(
sources: Seq[File],
destination: File,
semanticDbClassPath: ClassPath,
patches: Seq[Patch],
lib: Lib
) = {
val fromTo = lib.autoRelative( sources ).collect{
case (location, relative) if location.isFile
=> location -> destination / relative
}

Scalafix.apply(lib).config(
outer.classpath,
files = fromTo,
patches = lib_rewrites ++ version_rewrites,
allowEmpty = true
).apply
val to = fromTo.map(_._2)
assert( ( to diff to.distinct ).isEmpty )

to
}
}
}
Scalafix.apply(lib).config(
semanticDbClassPath,
files = fromTo,
patches = patches,
allowEmpty = true
).apply

to
}
}
}
6 changes: 5 additions & 1 deletion examples/cross-rewrite-example/src/Main.scala
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
import scala.concurrent.Future
object Main {
def main( args: Array[String] ): Unit = {
Disjunction.intOrString.map( println )
}
}
3 changes: 3 additions & 0 deletions examples/cross-rewrite-example/src/disjunction.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
object Disjunction {
val intOrString: Either[Int, String] = Right( "It works!" )
}
9 changes: 9 additions & 0 deletions examples/cross-rewrite-example/test/disjunction_spec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import org.scalatest._

class Test extends FunSpec with Matchers {
describe( "Disjunction" ) {
it( "should work in all versions" ) {
Disjunction.intOrString shouldBe Right( "It works!" )
}
}
}
45 changes: 25 additions & 20 deletions stage1/resolver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@ trait DependencyImplementation extends Dependency{
java_exe.string +: "-cp" +: classpath.string +: className +: args
)
} else {
lib.getMain( classLoader.loadClass( className ) )( args )
val cl = if( !flatClassLoader ) classLoader else {
new java.net.URLClassLoader(classpath.strings.map(f => new URL("file://" ++ f)).toArray)
}
lib.getMain( cl.loadClass( className ) )( args )
}
}

Expand All @@ -109,30 +112,26 @@ trait DependencyImplementation extends Dependency{
def flatClassLoader: Boolean = false

override def classLoader: ClassLoader = taskCache[DependencyImplementation]( "classLoader" ).memoize{
if( flatClassLoader ){
new java.net.URLClassLoader(classpath.strings.map(f => new URL("file://" ++ f)).toArray)
} else {
/*
if( concurrencyEnabled ){
// trigger concurrent building / downloading dependencies
exportClasspathConcurrently
}
*/
lib.classLoaderRecursion(
this,
(this +: transitiveDependencies).collect{
case d: ArtifactInfo => d
}.groupBy(
d => (d.groupId,d.artifactId)
).mapValues(_.head)
)
/*
if( concurrencyEnabled ){
// trigger concurrent building / downloading dependencies
exportClasspathConcurrently
}
*/
lib.classLoaderRecursion(
this,
(this +: transitiveDependencies).collect{
case d: ArtifactInfo => d
}.groupBy(
d => (d.groupId,d.artifactId)
).mapValues(_.head)
)
}

// FIXME: these probably need to update outdated as well
def classpath: ClassPath = exportedClasspath ++ dependencyClasspath
def verifyClasspath: Unit = classpath.verify(lib)
def dependencyClasspath: ClassPath = taskCache[DependencyImplementation]( "dependencyClasspath" ).memoize{
def dependencyClasspath: ClassPath = {
ClassPath(
transitiveDependencies
.flatMap(_.exportedClasspath.files)
Expand Down Expand Up @@ -369,7 +368,13 @@ case class BoundMavenDependency(
cbtLastModified, mavenCache ++ basePath(true) ++ ".pom.dependencies", classLoaderCache.hashMap
)( MavenDependency.deserialize )( _.serialize )( MavenDependency.dejavafy )( _.map(_.javafy).toArray ){
(pomXml \ "dependencies" \ "dependency").collect{
case xml if ( (xml \ "scope").text == "" || (xml \ "scope").text == "compile" ) && (xml \ "optional").text != "true" =>
case xml if (
(xml \ "scope").text == ""
// these are probably not right like this, but should be better than not having them for now
|| (xml \ "scope").text == "runtime"
|| (xml \ "scope").text == "compile"
|| (xml \ "scope").text == "provided"
) && (xml \ "optional").text != "true" =>
val artifactId = lookup(xml,_ \ "artifactId").get
val groupId =
lookup(xml,_ \ "groupId").getOrElse(
Expand Down
2 changes: 1 addition & 1 deletion stage2/BasicBuild.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ trait BaseBuild extends BuildInterface with DependencyImplementation with SbtDep
// will create new instances given the context, which means operations in the
// overrides will happen multiple times and if they are not idempotent stuff likely breaks
def context: Context
override lazy val moduleKey: String = "BaseBuild("+target.string+")"
override lazy val moduleKey: String = "BaseBuild("+target.string+","+context.scalaVersion+")"
implicit def transientCache: java.util.Map[AnyRef,AnyRef] = context.transientCache

object libraries extends libraries( context, scalaVersion, scalaMajorVersion )
Expand Down
2 changes: 2 additions & 0 deletions stage2/GitDependency.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ object GitDependency{
++ "(" ++ url ++ subDirectory.map("/" ++ _).getOrElse("") ++ "#" ++ ref
++ ", "
++ subBuild.mkString(", ")
++ ", "
++ context.scalaVersion.toString
++ ")"
)

Expand Down
2 changes: 1 addition & 1 deletion stage2/LazyDependency.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class LazyDependency( _dependency: => Dependency )( implicit logger: Logger, tra
def dependenciesArray = Array( dependency )
def exportedClasspathArray = Array()
override def lastModified = dependency.lastModified
override lazy val moduleKey = show
override lazy val moduleKey = "LazyDependency:" + dependency.moduleKey
def show = s"LazyDependency(${dependency.show})"
override def toString = show
override def equals( other: Any ) = other match {
Expand Down