-
Notifications
You must be signed in to change notification settings - Fork 60
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
WIP - adding example to cross-rewrite #466
base: master
Are you sure you want to change the base?
Conversation
class Build(val context: Context) extends BaseBuild{ outer => | ||
override def defaultScalaVersion = "2.11.8" | ||
class Build(val context: Context) extends BaseBuild { outer => | ||
override def defaultScalaVersion = "2.12.1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the default because I thought people might like to write code in the latest version and backwards compile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
override def test: Dependency = { | ||
new BasicBuild(context) with ScalaTest { | ||
override def dependencies = outer +: super.dependencies | ||
override def defaultScalaVersion = "2.12.1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this correct that I need to override version for test build (why would I ever want to test on a different version?)
Or should my test be extending my main project somehow to have access to the code in it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you overwrote defautScalaVersion is class Build
, but here you are instantiating class BasicBuild
. That's fine, but it doesn't magically pick up on what you overwrote in Build
. So if you want this as 2.12.1 you need to provide that info here somehow.
val fromTo = lib.autoRelative(outer.sources).collect { | ||
case (location, relative) if location.isFile => | ||
location -> projectDirectory / "src" / relative | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
scalafmt must have changed all of this slightly. Would you be interested in a pr adding a .scalafmt config to the project?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not completely warmed up to scalafmt yet. I played around with it a bit, but it currently does not allow me to produce code that I find as readable as scalariform. So for now I have settled on Scalariform for CBT and there is a preconfigured plugins.scalariform
plugin you can add as a dependency to your BuildBuild, allowing you to mix in Scalariform
into your build, which adds a preconfigured task scalariform
, which by default is not run on compile, but can be easily added (in which case one has to call scalariform.apply there, because it is lazy).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(had a longer discussion with olaf around the limitations of scalafmt for my personal preferred style a few weeks ago)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem. I don't mind using scalariform but I may take a shot at making a .scalafmt.conf that matches your scalariform preferences just to see if I can.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Scalafmt does not have any settings which mimic scalariform, they're very different formatters.
object Main { | ||
def main(args: Array[String]): Unit = { | ||
//For 2.11.8 rewrite to case match | ||
Disjunction.intOrString.map(println) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could either rewrite this to a case statement for scalaz 2.11.8 (I don't believe they have an either enrichment for map) or I could change the type to /. Either one would require the semantic mirror which I am not clear is actually available based on @olafurpg comment about ExplicitImplicit being available. I will experiment more once I get tests to pass.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a semantic mirror is available, just not the Scalafix Mirror, which ExplicitImplicit is currently coded against.
plugins/scalatest/ScalaTest.scala
Outdated
@@ -9,7 +9,7 @@ trait ScalaTest extends BaseBuild{ | |||
runSuites( suiteNames.map( loadSuite( _, classLoader ) ) ) | |||
ExitCode.Success | |||
} | |||
override def dependencies = super.dependencies ++ Resolver( mavenCentral ).bind( ScalaDependency("org.scalatest","scalatest","2.2.4") ) | |||
override def dependencies = super.dependencies ++ Resolver( mavenCentral ).bind( ScalaDependency("org.scalatest","scalatest","3.0.1") ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no 2.x version of Scalatest for scala 2.12 so I bumped to scalatest 3.0.1.
plugins/scalatest/build/build.scala
Outdated
@@ -5,6 +5,6 @@ class Build(val context: Context) extends BaseBuild{ | |||
super.dependencies | |||
:+ context.cbtDependency | |||
) ++ Resolver( mavenCentral ).bind( | |||
ScalaDependency("org.scalatest","scalatest","2.2.4") | |||
ScalaDependency("org.scalatest","scalatest","3.0.1") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't looked into this yet but don't like that there are these duplicated strings in multiple files. Maybe I need to create a Dependencies.scala file to share them.
val fromTo = lib.autoRelative(outer.sources).collect { | ||
case (location, relative) if location.isFile => | ||
location -> projectDirectory / "src" / relative | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(had a longer discussion with olaf around the limitations of scalafmt for my personal preferred style a few weeks ago)
object Main { | ||
def main(args: Array[String]): Unit = { | ||
//For 2.11.8 rewrite to case match | ||
Disjunction.intOrString.map(println) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a semantic mirror is available, just not the Scalafix Mirror, which ExplicitImplicit is currently coded against.
override def defaultScalaVersion = "2.12.1" | ||
|
||
override def test: Dependency = { | ||
new BasicBuild(context) with ScalaTest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you need to add override def projectDirectory = outer.projectDirectory / "test"
here, so it can find your source files. Otherwise it only looks in context.workingDirectory
and context.workingDirectory / "src"
. context.workingDirectory
is the default for BaseBuild.projectDirectory
and the directory one up from the build.scala file. I'd suggest you look start looking into the source code a little bit. CBT makes that quite easy :).
the tests check for the existence of a cats AND scalaz crossbuilds, which is why this still fails ;). |
Ah, that makes sense. That should be easy enough for me to resolve Saturday. |
Replace(Symbol("_root_.Disjunction."), q"Test"), | ||
Rename(q"intOrString", q"xor"), | ||
//And this works again. What is different about import rewrites vs the others? | ||
RemoveGlobalImport(importer"scala.concurrent.Future") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure if I am missing something or if there is a bug in scalafix, but import releated rewrites work and others do not. I can't tell what the difference is yet. I looked back through scalafix code and these are all instances of TreePatch. Once the patching works this should be as simple as adding scalaz./, replacing Either with / and Right with /-
//None of these work, why? | ||
Replace(Symbol("_root_.scala.util.Either."), q"\/"), | ||
Replace(Symbol("_root_.Disjunction."), q"Test"), | ||
Rename(q"intOrString", q"xor"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename
should probably be called RenameThisInstance
(or similar) because it's reference based, I opened scalacenter/scalafix#109 to track that change. To replace call-sites of a specific definition you want to use Replace
, which is symbol based.
//This works | ||
AddGlobalImport(importer"scalaz._"), | ||
//None of these work, why? | ||
Replace(Symbol("_root_.scala.util.Either."), q"\/"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you tried Mirror.database.toString
to double check that this symbol matches the symbol you want to rewrite? Otherwise, please open an issue in scalafix and I can take a look at it next week.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The type of scala.util.Either is actually scala.package.Either. Printing out the mirror.database helped, thanks @olafurpg
plugins/scalafix/Scalafix.scala
Outdated
println("printing mirror database messages") | ||
println(ctx.mirror.database) | ||
println("end printing") | ||
assert(ctx.mirror.database.toString.trim != "", "I do not believe the database should be empty here") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@olafurpg The semantic db appears to be empty here even though sources is not. Do you think the semantic db is being constructed incorrectly, or that I should open a scalameta issue on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The project source files need to be compiled with the scalahost compiler plugin for the database to be built, so the Scalameta
plugin needs to be mixed in the root build. The mirror is composed of a classpath
(pointing to at least one directory containing semanticdb
files) and a sourcepath
(pointing to scala source files). In this case, the classpath does not contain any semanticdb files, maybe the Mirror constructor should fail in that case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do believe fail fast would be better here, but this should be enough to advice to get me back on track. 👍
plugins/scalafix/Scalafix.scala
Outdated
Mirror( | ||
classpath.string, | ||
files.map(_._1).mkString(File.pathSeparator) | ||
) | ||
} | ||
|
||
def context(file: File): ( RewriteCtx[Mirror], RewriteCtx[ScalafixMirror] ) = ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RewriteCtx[ScalafixMirror]
is not necessary here, ScalafixMirror
will go away in favor of Mirror
.
@@ -6,67 +6,101 @@ import scalafix.util._ | |||
import scalafix.util.TreePatch._ | |||
import scalafix.util.TokenPatch._ | |||
|
|||
class Build(val context: Context) extends BaseBuild{ outer => | |||
class Build(val context: Context) extends BaseBuild { outer => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's missing a with Scalameta
here to inject the scalahost compiler plugin, which generates semanticdb
files under target/
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doh! Thanks for catching that.
val fromTo = lib.autoRelative(outer.sources).collect { | ||
case (location, relative) if location.isFile => | ||
location -> projectDirectory / "src" / relative | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Scalafmt does not have any settings which mimic scalariform, they're very different formatters.
plugins/scalafix/Scalafix.scala
Outdated
println("printing mirror database messages") | ||
println(ctx.mirror.database) | ||
println("end printing") | ||
assert(ctx.mirror.database.toString.trim != "", "I do not believe the database should be empty here") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The project source files need to be compiled with the scalahost compiler plugin for the database to be built, so the Scalameta
plugin needs to be mixed in the root build. The mirror is composed of a classpath
(pointing to at least one directory containing semanticdb
files) and a sourcepath
(pointing to scala source files). In this case, the classpath does not contain any semanticdb files, maybe the Mirror constructor should fail in that case.
//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 | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ignore everything below here, I didn't mean to commit it.
would contain wrong classLoader when switching scalaVersions)
otherwise those libraries wouldn’t find the classes we might have to reconsider this eventually
running something, not the one that may end up in a cache
rather than the more obscure context object
(there is still a test failure, where the code hasn’t been rewritten properly, but that’s ok. One step at a time.)
I forgot all about this PR. Will try to take a look at it in a few days and see if I can figure out why tests fail. |
This is not even close to ready, just making a pr to see if I am on the right track.