From 78d016448a76d8a58b25de5149abc7cdd4bd3874 Mon Sep 17 00:00:00 2001 From: Shane Delmore Date: Sat, 8 Apr 2017 10:31:20 -0700 Subject: [PATCH 01/12] Adding rewrite and test examples from 2.12 to 2.11 with cats and scalaz --- .../cross-rewrite-example/build/build.scala | 43 ++++++++++++++++--- examples/cross-rewrite-example/src/Main.scala | 6 ++- .../src/disjunction.scala | 3 ++ .../test/disjunction_spec.scala | 10 +++++ 4 files changed, 55 insertions(+), 7 deletions(-) create mode 100644 examples/cross-rewrite-example/src/disjunction.scala create mode 100644 examples/cross-rewrite-example/test/disjunction_spec.scala diff --git a/examples/cross-rewrite-example/build/build.scala b/examples/cross-rewrite-example/build/build.scala index 6d2ffac5..06f73271 100644 --- a/examples/cross-rewrite-example/build/build.scala +++ b/examples/cross-rewrite-example/build/build.scala @@ -6,12 +6,30 @@ 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 Build(val context: Context) extends BaseBuild with Scalameta { outer => + override def defaultScalaVersion = "2.12.1" + + override def test: Dependency = { + new BasicBuild(context) with ScalaTest { + override def dependencies = outer +: super.dependencies + override def defaultScalaVersion = outer.scalaVersion + override def sources = Seq(context.workingDirectory / "test") + override def projectDirectory = { + val d = outer.projectDirectory / "test" + d.mkdirs + d + } + } + } + +// case class CrossRewrite(name: String, patches: Seq[Patch], scalaVersion: Option[ScalaVersion], lib: Option[String]) +// +// case class AddDependency(dep: MavenDependency) +// case class RemoveDependency(dep: MavenDependency) def versions = Seq[(String, Seq[Patch])]( scalaVersion -> Seq(), - "2.12.1" -> Seq( + "2.11.8" -> Seq( RemoveGlobalImport( importer"scala.concurrent.Future" ), @@ -23,14 +41,19 @@ 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._") ) ) ) @@ -45,7 +68,15 @@ class Build(val context: Context) extends BaseBuild{ outer => 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 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 projectDirectory = d override def scaladoc = None override def sources = { diff --git a/examples/cross-rewrite-example/src/Main.scala b/examples/cross-rewrite-example/src/Main.scala index 27ea3ff1..ae35c74a 100644 --- a/examples/cross-rewrite-example/src/Main.scala +++ b/examples/cross-rewrite-example/src/Main.scala @@ -1 +1,5 @@ -import scala.concurrent.Future +object Main { + def main(args: Array[String]): Unit = { + Disjunction.intOrString.map(println) + } +} diff --git a/examples/cross-rewrite-example/src/disjunction.scala b/examples/cross-rewrite-example/src/disjunction.scala new file mode 100644 index 00000000..4290c56f --- /dev/null +++ b/examples/cross-rewrite-example/src/disjunction.scala @@ -0,0 +1,3 @@ +object Disjunction { + val intOrString: Either[Int, String] = Right("It works!") +} diff --git a/examples/cross-rewrite-example/test/disjunction_spec.scala b/examples/cross-rewrite-example/test/disjunction_spec.scala new file mode 100644 index 00000000..e4482ee4 --- /dev/null +++ b/examples/cross-rewrite-example/test/disjunction_spec.scala @@ -0,0 +1,10 @@ +import collection.mutable.Stack +import org.scalatest._ + +class Test extends FunSpec with Matchers { + describe("Disjunction") { + it("should work in all versions") { + Disjunction.intOrString shouldBe Right("It works!") + } + } +} From e4404db64229f32ac41bf86a95bd590e2bece41a Mon Sep 17 00:00:00 2001 From: Shane Delmore Date: Sat, 8 Apr 2017 14:10:29 -0700 Subject: [PATCH 02/12] Demonstration of build api I have in my head. --- .../cross-rewrite-example/build/build.scala | 86 ++++++++++++++++++- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/examples/cross-rewrite-example/build/build.scala b/examples/cross-rewrite-example/build/build.scala index 06f73271..28fbbc09 100644 --- a/examples/cross-rewrite-example/build/build.scala +++ b/examples/cross-rewrite-example/build/build.scala @@ -6,11 +6,48 @@ import scalafix.util._ import scalafix.util.TreePatch._ import scalafix.util.TokenPatch._ + object DayDreaming { + + val imaginaryBaseBuild = BaseBuild( + context = Context, + defaultScalaVersion = "2.12.1" + ) + .map(addPlugin(Scalameta)) + .map(addPlugin(Scalatest)) //I would expect to normally use the default test directory config + .map(addPlugin(CrossBuild)) + .map(addPlugin(CrossRewriter)) + .map { build => //I would expect that here I would have Build with MetaBuild with ScalaTestBuild with CrossBuild with CrossRewriter + build.copy( + crossBuilds = Seq( //This would be a sequence of build transforms. If I had many I would create a function to build a matrix of transforms + setVersion("2.11.8") andThen + addDependency(MavenDependency("org.scalaz", "scalaz-core", "7.2.10")) andThen + transformSources( //transformSources would be in CrossRewriter plugin and would apply rewrites to all sources + AddGlobalImport(importer"scalaz._"), + Replace(Symbol("_root_.scala.package.Either."), q"\/"), + Replace(Symbol("_root_.scala.util.Right."), q"\/-"), + RemoveGlobalImport(importer"cats.implicits._") + ), + setVersion("2.11.8") andThen + addDependency(MavenDependency("org.typelevel", "cats", "0.9.0")) andThen + transformSources(AddGlobalImport(importer"cats.implicits._")) + ) + ) + } + + def setVersion(version: String): Build => Build = _.copy(scalaVersion = version) + def addDependency(dep: MavenDependency): Build => Build = _.copy(dependencies = dependencies :+ dep) + def removeDependency(dep: MavenDependency): Build => Build = _.copy(dependencies = dependencies :- dep) + + //Over time I would hope to build up a community libraryof rewrites so many of the transforms would be pulled from + //a library instead of declared in the build + } + class Build(val context: Context) extends BaseBuild with Scalameta { outer => override def defaultScalaVersion = "2.12.1" override def test: Dependency = { new BasicBuild(context) with ScalaTest { + def apply = run override def dependencies = outer +: super.dependencies override def defaultScalaVersion = outer.scalaVersion override def sources = Seq(context.workingDirectory / "test") @@ -28,7 +65,7 @@ class Build(val context: Context) extends BaseBuild with Scalameta { outer => // case class RemoveDependency(dep: MavenDependency) def versions = Seq[(String, Seq[Patch])]( - scalaVersion -> Seq(), +// scalaVersion -> Seq(), "2.11.8" -> Seq( RemoveGlobalImport( importer"scala.concurrent.Future" @@ -82,7 +119,7 @@ class Build(val context: Context) extends BaseBuild with Scalameta { outer => override def sources = { val fromTo = lib.autoRelative( outer.sources ).collect{ case (location, relative) if location.isFile - => location -> projectDirectory / "src" / relative + => location -> projectDirectory / "src" / relative } val to = fromTo.map(_._2) @@ -97,6 +134,51 @@ class Build(val context: Context) extends BaseBuild with Scalameta { outer => to } + + override def test: Dependency = { + val testDirectory = projectDirectory / "test" + new BasicBuild( context.copy(workingDirectory = testDirectory) ) with ScalaTest { +// def apply = run + + override def dependencies = outer +: super.dependencies + + override def defaultScalaVersion = v + + override def sources = Seq(context.workingDirectory / "test") + + override def projectDirectory = { + val d = outer.projectDirectory / "test" + d.mkdirs + d + } + } + } + +// with +// { +// override def sources +// +// = +// { +// val fromTo = lib.autoRelative(outer.sources).collect { +// case (location, relative) if location.isFile +// => location -> projectDirectory / "src" / relative +// } +// +// val to = fromTo.map(_._2) +// assert((to diff to.distinct).isEmpty) +// +// Scalafix.apply(lib).config( +// outer.classpath, +// files = fromTo, +// patches = lib_rewrites ++ version_rewrites, +// allowEmpty = true +// ).apply +// +// to +// } +// } + } } } From b0ab650da73dbc0986a82a9a82d48bc243622a6a Mon Sep 17 00:00:00 2001 From: Christopher Vogt Date: Sun, 9 Apr 2017 00:57:39 -0400 Subject: [PATCH 03/12] fix moduleKey cache keys to respect scalaVersion (otherwise cache would contain wrong classLoader when switching scalaVersions) --- stage1/resolver.scala | 2 +- stage2/BasicBuild.scala | 2 +- stage2/GitDependency.scala | 2 ++ stage2/LazyDependency.scala | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/stage1/resolver.scala b/stage1/resolver.scala index f4a9b13d..48dd2f23 100644 --- a/stage1/resolver.scala +++ b/stage1/resolver.scala @@ -132,7 +132,7 @@ trait DependencyImplementation extends Dependency{ // 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) diff --git a/stage2/BasicBuild.scala b/stage2/BasicBuild.scala index 05e3c41c..a28c8609 100644 --- a/stage2/BasicBuild.scala +++ b/stage2/BasicBuild.scala @@ -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 ) diff --git a/stage2/GitDependency.scala b/stage2/GitDependency.scala index 8a4a4413..26d758a0 100644 --- a/stage2/GitDependency.scala +++ b/stage2/GitDependency.scala @@ -22,6 +22,8 @@ object GitDependency{ ++ "(" ++ url ++ subDirectory.map("/" ++ _).getOrElse("") ++ "#" ++ ref ++ ", " ++ subBuild.mkString(", ") + ++ ", " + ++ context.scalaVersion.toString ++ ")" ) diff --git a/stage2/LazyDependency.scala b/stage2/LazyDependency.scala index 2822638c..2cfcd273 100644 --- a/stage2/LazyDependency.scala +++ b/stage2/LazyDependency.scala @@ -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 { From 82e5b41617650c9d93069c76c9f7b5160b6c6eea Mon Sep 17 00:00:00 2001 From: Christopher Vogt Date: Sun, 9 Apr 2017 00:58:47 -0400 Subject: [PATCH 04/12] =?UTF-8?q?treat=20provided=20and=20runtime=20depend?= =?UTF-8?q?encies=20as=20mandatory=20ones=20for=20now=20otherwise=20those?= =?UTF-8?q?=20libraries=20wouldn=E2=80=99t=20find=20the=20classes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit we might have to reconsider this eventually --- stage1/resolver.scala | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/stage1/resolver.scala b/stage1/resolver.scala index 48dd2f23..380b460a 100644 --- a/stage1/resolver.scala +++ b/stage1/resolver.scala @@ -369,7 +369,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( From 960d3fd356b90ca540241987a6e0ab5546e78195 Mon Sep 17 00:00:00 2001 From: Christopher Vogt Date: Sun, 9 Apr 2017 00:59:20 -0400 Subject: [PATCH 05/12] flatClassLoader should probably only affect the classLoader used when running something, not the one that may end up in a cache --- stage1/resolver.scala | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/stage1/resolver.scala b/stage1/resolver.scala index 380b460a..e60260fe 100644 --- a/stage1/resolver.scala +++ b/stage1/resolver.scala @@ -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 ) } } @@ -109,24 +112,20 @@ 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 From 0d25c347b0301b0ede3829ebfce4fe6dfef3fbfb Mon Sep 17 00:00:00 2001 From: Christopher Vogt Date: Sun, 9 Apr 2017 01:05:26 -0400 Subject: [PATCH 06/12] disable DayDreaming --- examples/cross-rewrite-example/build/build.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/cross-rewrite-example/build/build.scala b/examples/cross-rewrite-example/build/build.scala index 28fbbc09..366b39ce 100644 --- a/examples/cross-rewrite-example/build/build.scala +++ b/examples/cross-rewrite-example/build/build.scala @@ -6,8 +6,9 @@ import scalafix.util._ import scalafix.util.TreePatch._ import scalafix.util.TokenPatch._ - object DayDreaming { +/* + object DayDreaming { val imaginaryBaseBuild = BaseBuild( context = Context, defaultScalaVersion = "2.12.1" @@ -41,6 +42,7 @@ import scalafix.util.TokenPatch._ //Over time I would hope to build up a community libraryof rewrites so many of the transforms would be pulled from //a library instead of declared in the build } +*/ class Build(val context: Context) extends BaseBuild with Scalameta { outer => override def defaultScalaVersion = "2.12.1" From d7209c464176534304734d08781605af9099253d Mon Sep 17 00:00:00 2001 From: Christopher Vogt Date: Sun, 9 Apr 2017 01:10:47 -0400 Subject: [PATCH 07/12] =?UTF-8?q?name=20default=20build=20self=20name=20mo?= =?UTF-8?q?re=20clearly=20and=20refer=20to=20it=E2=80=99s=20fields=20rathe?= =?UTF-8?q?r=20than=20the=20more=20obscure=20context=20object?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cross-rewrite-example/build/build.scala | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/examples/cross-rewrite-example/build/build.scala b/examples/cross-rewrite-example/build/build.scala index 366b39ce..7f0f00ae 100644 --- a/examples/cross-rewrite-example/build/build.scala +++ b/examples/cross-rewrite-example/build/build.scala @@ -43,18 +43,15 @@ import scalafix.util.TokenPatch._ //a library instead of declared in the build } */ +class Build(val context: Context) extends BaseBuild with Scalameta { defaultMainBuild => + override def defaultScalaVersion: String = "2.12.1" -class Build(val context: Context) extends BaseBuild with Scalameta { outer => - override def defaultScalaVersion = "2.12.1" - - override def test: Dependency = { + override def test: BasicBuild = { new BasicBuild(context) with ScalaTest { - def apply = run - override def dependencies = outer +: super.dependencies - override def defaultScalaVersion = outer.scalaVersion - override def sources = Seq(context.workingDirectory / "test") + override def dependencies = defaultMainBuild +: super.dependencies + override def defaultScalaVersion = defaultMainBuild.scalaVersion override def projectDirectory = { - val d = outer.projectDirectory / "test" + val d = defaultMainBuild.projectDirectory / "test" d.mkdirs d } @@ -100,7 +97,7 @@ class Build(val context: Context) extends BaseBuild with Scalameta { outer => def cross = versions.flatMap{ case ( v, version_rewrites ) => libs.map{ case ( label, dep, lib_rewrites ) => - val d = outer.target / "rewrites" / label ++ "-" ++ v + val d = defaultMainBuild.target / "rewrites" / label ++ "-" ++ v d.mkdirs new Build(context) with Scalafix with PackageJars{ override def groupId = "org.cvogt" @@ -119,7 +116,7 @@ class Build(val context: Context) extends BaseBuild with Scalameta { outer => override def projectDirectory = d override def scaladoc = None override def sources = { - val fromTo = lib.autoRelative( outer.sources ).collect{ + val fromTo = lib.autoRelative( defaultMainBuild.sources ).collect{ case (location, relative) if location.isFile => location -> projectDirectory / "src" / relative } @@ -128,7 +125,7 @@ class Build(val context: Context) extends BaseBuild with Scalameta { outer => assert( ( to diff to.distinct ).isEmpty ) Scalafix.apply(lib).config( - outer.classpath, + defaultMainBuild.classpath, files = fromTo, patches = lib_rewrites ++ version_rewrites, allowEmpty = true @@ -142,17 +139,17 @@ class Build(val context: Context) extends BaseBuild with Scalameta { outer => new BasicBuild( context.copy(workingDirectory = testDirectory) ) with ScalaTest { // def apply = run - override def dependencies = outer +: super.dependencies override def defaultScalaVersion = v override def sources = Seq(context.workingDirectory / "test") override def projectDirectory = { - val d = outer.projectDirectory / "test" - d.mkdirs - d + val dt = defaultMainBuild.projectDirectory / "test" + dt.mkdirs + dt } + override def dependencies = patchedMainBuild +: super.dependencies } } From 7c1e2f4220860b0a0372f7efa6d0f0052e9b0d95 Mon Sep 17 00:00:00 2001 From: Christopher Vogt Date: Sun, 9 Apr 2017 01:29:47 -0400 Subject: [PATCH 08/12] =?UTF-8?q?fixing=20cross-build-example=20tests=20to?= =?UTF-8?q?=20run=20across=20versions=20(there=20is=20still=20a=20test=20f?= =?UTF-8?q?ailure,=20where=20the=20code=20hasn=E2=80=99t=20been=20rewritte?= =?UTF-8?q?n=20properly,=20but=20that=E2=80=99s=20ok.=20One=20step=20at=20?= =?UTF-8?q?a=20time.)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cross-rewrite-example/build/build.scala | 61 ++++++++----------- 1 file changed, 24 insertions(+), 37 deletions(-) diff --git a/examples/cross-rewrite-example/build/build.scala b/examples/cross-rewrite-example/build/build.scala index 7f0f00ae..30d658df 100644 --- a/examples/cross-rewrite-example/build/build.scala +++ b/examples/cross-rewrite-example/build/build.scala @@ -64,7 +64,7 @@ class Build(val context: Context) extends BaseBuild with Scalameta { defaultMain // case class RemoveDependency(dep: MavenDependency) def versions = Seq[(String, Seq[Patch])]( -// scalaVersion -> Seq(), + "2.12.1" -> Seq(), "2.11.8" -> Seq( RemoveGlobalImport( importer"scala.concurrent.Future" @@ -99,7 +99,7 @@ class Build(val context: Context) extends BaseBuild with Scalameta { defaultMain case ( label, dep, lib_rewrites ) => val d = defaultMainBuild.target / "rewrites" / label ++ "-" ++ v d.mkdirs - new Build(context) with Scalafix with PackageJars{ + new Build(context) with Scalafix with PackageJars{ patchedMainBuild => override def groupId = "org.cvogt" override def artifactId = "cbt-examples-cross-rewrite-" + label override def version = "0.1" @@ -134,50 +134,37 @@ class Build(val context: Context) extends BaseBuild with Scalameta { defaultMain to } - override def test: Dependency = { - val testDirectory = projectDirectory / "test" - new BasicBuild( context.copy(workingDirectory = testDirectory) ) with ScalaTest { -// def apply = run - - + override def test = { + new BasicBuild( context ) with ScalaTest { patchedTestBuild => override def defaultScalaVersion = v - - override def sources = Seq(context.workingDirectory / "test") - override def projectDirectory = { val dt = defaultMainBuild.projectDirectory / "test" dt.mkdirs dt } override def dependencies = patchedMainBuild +: super.dependencies - } - } + override def target = super.target / v ~ "-" ~ label -// with -// { -// override def sources -// -// = -// { -// val fromTo = lib.autoRelative(outer.sources).collect { -// case (location, relative) if location.isFile -// => location -> projectDirectory / "src" / relative -// } -// -// val to = fromTo.map(_._2) -// assert((to diff to.distinct).isEmpty) -// -// Scalafix.apply(lib).config( -// outer.classpath, -// files = fromTo, -// patches = lib_rewrites ++ version_rewrites, -// allowEmpty = true -// ).apply -// -// to -// } -// } + override def sources = { + val fromTo = lib.autoRelative( defaultMainBuild.test.sources ).collect{ + case (location, relative) if location.isFile + => location -> target / "src" / relative + } + + val to = fromTo.map(_._2) + assert( ( to diff to.distinct ).isEmpty ) + + Scalafix.apply(lib).config( + defaultMainBuild.test.classpath, + files = fromTo, + patches = lib_rewrites ++ version_rewrites, + allowEmpty = true + ).apply + to + } + } + } } } } From 4a6814d2a291ef3133086d9b0446d4e03deb482e Mon Sep 17 00:00:00 2001 From: Shane Delmore Date: Sun, 9 Apr 2017 10:42:48 -0700 Subject: [PATCH 09/12] All tests pass. --- .../cross-rewrite-example/build/build.scala | 44 +------------------ .../test/disjunction_spec.scala | 1 - 2 files changed, 1 insertion(+), 44 deletions(-) diff --git a/examples/cross-rewrite-example/build/build.scala b/examples/cross-rewrite-example/build/build.scala index 30d658df..33b38681 100644 --- a/examples/cross-rewrite-example/build/build.scala +++ b/examples/cross-rewrite-example/build/build.scala @@ -6,48 +6,11 @@ import scalafix.util._ import scalafix.util.TreePatch._ import scalafix.util.TokenPatch._ - -/* - object DayDreaming { - val imaginaryBaseBuild = BaseBuild( - context = Context, - defaultScalaVersion = "2.12.1" - ) - .map(addPlugin(Scalameta)) - .map(addPlugin(Scalatest)) //I would expect to normally use the default test directory config - .map(addPlugin(CrossBuild)) - .map(addPlugin(CrossRewriter)) - .map { build => //I would expect that here I would have Build with MetaBuild with ScalaTestBuild with CrossBuild with CrossRewriter - build.copy( - crossBuilds = Seq( //This would be a sequence of build transforms. If I had many I would create a function to build a matrix of transforms - setVersion("2.11.8") andThen - addDependency(MavenDependency("org.scalaz", "scalaz-core", "7.2.10")) andThen - transformSources( //transformSources would be in CrossRewriter plugin and would apply rewrites to all sources - AddGlobalImport(importer"scalaz._"), - Replace(Symbol("_root_.scala.package.Either."), q"\/"), - Replace(Symbol("_root_.scala.util.Right."), q"\/-"), - RemoveGlobalImport(importer"cats.implicits._") - ), - setVersion("2.11.8") andThen - addDependency(MavenDependency("org.typelevel", "cats", "0.9.0")) andThen - transformSources(AddGlobalImport(importer"cats.implicits._")) - ) - ) - } - - def setVersion(version: String): Build => Build = _.copy(scalaVersion = version) - def addDependency(dep: MavenDependency): Build => Build = _.copy(dependencies = dependencies :+ dep) - def removeDependency(dep: MavenDependency): Build => Build = _.copy(dependencies = dependencies :- dep) - - //Over time I would hope to build up a community libraryof rewrites so many of the transforms would be pulled from - //a library instead of declared in the build - } -*/ class Build(val context: Context) extends BaseBuild with Scalameta { defaultMainBuild => override def defaultScalaVersion: String = "2.12.1" override def test: BasicBuild = { - new BasicBuild(context) with ScalaTest { + new BasicBuild(context) with ScalaTest with Scalameta { override def dependencies = defaultMainBuild +: super.dependencies override def defaultScalaVersion = defaultMainBuild.scalaVersion override def projectDirectory = { @@ -58,11 +21,6 @@ class Build(val context: Context) extends BaseBuild with Scalameta { defaultMain } } -// case class CrossRewrite(name: String, patches: Seq[Patch], scalaVersion: Option[ScalaVersion], lib: Option[String]) -// -// case class AddDependency(dep: MavenDependency) -// case class RemoveDependency(dep: MavenDependency) - def versions = Seq[(String, Seq[Patch])]( "2.12.1" -> Seq(), "2.11.8" -> Seq( diff --git a/examples/cross-rewrite-example/test/disjunction_spec.scala b/examples/cross-rewrite-example/test/disjunction_spec.scala index e4482ee4..034d65ea 100644 --- a/examples/cross-rewrite-example/test/disjunction_spec.scala +++ b/examples/cross-rewrite-example/test/disjunction_spec.scala @@ -1,4 +1,3 @@ -import collection.mutable.Stack import org.scalatest._ class Test extends FunSpec with Matchers { From ef93427206e10f09da69bd641c4331fff5d736f5 Mon Sep 17 00:00:00 2001 From: Christopher Vogt Date: Sun, 9 Apr 2017 15:07:11 -0400 Subject: [PATCH 10/12] factor logic out into helpers --- .../cross-rewrite-example/build/build.scala | 143 +++++++++--------- 1 file changed, 75 insertions(+), 68 deletions(-) diff --git a/examples/cross-rewrite-example/build/build.scala b/examples/cross-rewrite-example/build/build.scala index 33b38681..339cd84a 100644 --- a/examples/cross-rewrite-example/build/build.scala +++ b/examples/cross-rewrite-example/build/build.scala @@ -21,39 +21,10 @@ class Build(val context: Context) extends BaseBuild with Scalameta { defaultMain } } - def versions = Seq[(String, Seq[Patch])]( - "2.12.1" -> Seq(), - "2.11.8" -> Seq( - RemoveGlobalImport( - importer"scala.concurrent.Future" - ), - AddGlobalImport( - importer"scala.util.Try" - ) - ) - ) - def libs = Seq[(String, MavenDependency, Seq[Patch])]( - ( - "scalaz", - 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", - MavenDependency( "org.typelevel", "cats", "0.9.0" ), - Seq( - AddGlobalImport(importer"cats.implicits._") - ) - ) - ) + import CrossRewrite._ - def cross = versions.flatMap{ case ( v, version_rewrites ) => - libs.map{ + def cross = CrossRewrite.versions.flatMap{ case ( v, version_rewrites ) => + CrossRewrite.libs.map{ case ( label, dep, lib_rewrites ) => val d = defaultMainBuild.target / "rewrites" / label ++ "-" ++ v d.mkdirs @@ -73,24 +44,13 @@ class Build(val context: Context) extends BaseBuild with Scalameta { defaultMain ) override def projectDirectory = d override def scaladoc = None - override def sources = { - val fromTo = lib.autoRelative( defaultMainBuild.sources ).collect{ - case (location, relative) if location.isFile - => location -> projectDirectory / "src" / relative - } - - val to = fromTo.map(_._2) - assert( ( to diff to.distinct ).isEmpty ) - - Scalafix.apply(lib).config( - defaultMainBuild.classpath, - files = fromTo, - patches = lib_rewrites ++ version_rewrites, - allowEmpty = true - ).apply - - to - } + override def sources = CrossRewrite.patchesSources( + defaultMainBuild.sources, + projectDirectory / "src", + defaultMainBuild.classpath, + lib_rewrites ++ version_rewrites, + lib + ) override def test = { new BasicBuild( context ) with ScalaTest { patchedTestBuild => @@ -103,27 +63,74 @@ class Build(val context: Context) extends BaseBuild with Scalameta { defaultMain override def dependencies = patchedMainBuild +: super.dependencies override def target = super.target / v ~ "-" ~ label - override def sources = { - val fromTo = lib.autoRelative( defaultMainBuild.test.sources ).collect{ - case (location, relative) if location.isFile - => location -> target / "src" / relative - } - - val to = fromTo.map(_._2) - assert( ( to diff to.distinct ).isEmpty ) - - Scalafix.apply(lib).config( - defaultMainBuild.test.classpath, - files = fromTo, - patches = lib_rewrites ++ version_rewrites, - allowEmpty = true - ).apply - - to - } + override def sources = CrossRewrite.patchesSources( + defaultMainBuild.test.sources, + target / "src", + defaultMainBuild.test.classpath, + lib_rewrites ++ version_rewrites, + lib + ) } } } } } } + +object CrossRewrite{ + def versions = Seq[(String, Seq[Patch])]( + "2.12.1" -> Seq(), + "2.11.8" -> Seq( + RemoveGlobalImport( + importer"scala.concurrent.Future" + ), + AddGlobalImport( + importer"scala.util.Try" + ) + ) + ) + def libs = Seq[(String, MavenDependency, Seq[Patch])]( + ( + "scalaz", + 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", + MavenDependency( "org.typelevel", "cats", "0.9.0" ), + Seq( + AddGlobalImport(importer"cats.implicits._") + ) + ) + ) + + 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 + } + + val to = fromTo.map(_._2) + assert( ( to diff to.distinct ).isEmpty ) + + Scalafix.apply(lib).config( + semanticDbClassPath, + files = fromTo, + patches = patches, + allowEmpty = true + ).apply + + to + } +} \ No newline at end of file From 15c885926a6848a0760ce0a5564de1f1e5adfb73 Mon Sep 17 00:00:00 2001 From: Christopher Vogt Date: Sun, 9 Apr 2017 15:29:47 -0400 Subject: [PATCH 11/12] clean up cross-rewrite-example (more uniform) --- .../cross-rewrite-example/build/build.scala | 115 ++++++++---------- 1 file changed, 52 insertions(+), 63 deletions(-) diff --git a/examples/cross-rewrite-example/build/build.scala b/examples/cross-rewrite-example/build/build.scala index 339cd84a..009108ea 100644 --- a/examples/cross-rewrite-example/build/build.scala +++ b/examples/cross-rewrite-example/build/build.scala @@ -6,73 +6,57 @@ import scalafix.util._ import scalafix.util.TreePatch._ import scalafix.util.TokenPatch._ -class Build(val context: Context) extends BaseBuild with Scalameta { defaultMainBuild => - override def defaultScalaVersion: String = "2.12.1" - - override def test: BasicBuild = { - new BasicBuild(context) with ScalaTest with Scalameta { - override def dependencies = defaultMainBuild +: super.dependencies - override def defaultScalaVersion = defaultMainBuild.scalaVersion - override def projectDirectory = { - val d = defaultMainBuild.projectDirectory / "test" - d.mkdirs - d - } - } - } +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 +} - import CrossRewrite._ +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 - def cross = CrossRewrite.versions.flatMap{ case ( v, version_rewrites ) => - CrossRewrite.libs.map{ - case ( label, dep, lib_rewrites ) => - val d = defaultMainBuild.target / "rewrites" / label ++ "-" ++ v - d.mkdirs - new Build(context) with Scalafix with PackageJars{ patchedMainBuild => - 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( - // 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 projectDirectory = d - override def scaladoc = None - override def sources = CrossRewrite.patchesSources( - defaultMainBuild.sources, - projectDirectory / "src", - defaultMainBuild.classpath, - lib_rewrites ++ version_rewrites, - lib - ) + override def test: BaseBuild = new TestBuild( context, this ) - override def test = { - new BasicBuild( context ) with ScalaTest { patchedTestBuild => - override def defaultScalaVersion = v - override def projectDirectory = { - val dt = defaultMainBuild.projectDirectory / "test" - dt.mkdirs - dt - } - override def dependencies = patchedMainBuild +: super.dependencies - override def target = super.target / v ~ "-" ~ label + 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 sources = CrossRewrite.patchesSources( - defaultMainBuild.test.sources, - target / "src", - defaultMainBuild.test.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 + ) + } } } } @@ -109,6 +93,11 @@ object CrossRewrite{ ) ) + def mkdirIfNotExists( d: File ): File = { + d.mkdirs + d + } + def patchesSources( sources: Seq[File], destination: File, From c63a0462dc9277130a5d328437f71b1b7fac7135 Mon Sep 17 00:00:00 2001 From: Christopher Vogt Date: Sun, 9 Apr 2017 15:46:12 -0400 Subject: [PATCH 12/12] format code (breaks rewrites!) --- examples/cross-rewrite-example/src/Main.scala | 4 ++-- examples/cross-rewrite-example/src/disjunction.scala | 2 +- examples/cross-rewrite-example/test/disjunction_spec.scala | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/cross-rewrite-example/src/Main.scala b/examples/cross-rewrite-example/src/Main.scala index ae35c74a..d052a6d2 100644 --- a/examples/cross-rewrite-example/src/Main.scala +++ b/examples/cross-rewrite-example/src/Main.scala @@ -1,5 +1,5 @@ object Main { - def main(args: Array[String]): Unit = { - Disjunction.intOrString.map(println) + def main( args: Array[String] ): Unit = { + Disjunction.intOrString.map( println ) } } diff --git a/examples/cross-rewrite-example/src/disjunction.scala b/examples/cross-rewrite-example/src/disjunction.scala index 4290c56f..97686b80 100644 --- a/examples/cross-rewrite-example/src/disjunction.scala +++ b/examples/cross-rewrite-example/src/disjunction.scala @@ -1,3 +1,3 @@ object Disjunction { - val intOrString: Either[Int, String] = Right("It works!") + val intOrString: Either[Int, String] = Right( "It works!" ) } diff --git a/examples/cross-rewrite-example/test/disjunction_spec.scala b/examples/cross-rewrite-example/test/disjunction_spec.scala index 034d65ea..58c63fdd 100644 --- a/examples/cross-rewrite-example/test/disjunction_spec.scala +++ b/examples/cross-rewrite-example/test/disjunction_spec.scala @@ -1,9 +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!") + describe( "Disjunction" ) { + it( "should work in all versions" ) { + Disjunction.intOrString shouldBe Right( "It works!" ) } } }