scalafix icon indicating copy to clipboard operation
scalafix copied to clipboard

scalameta 4.9.x

Open bjaglin opened this issue 1 year ago • 4 comments
trafficstars

https://github.com/scalameta/scalameta/releases/tag/v4.9.0

https://github.com/scalameta/scalameta/issues/3425 is a non-backward compatible feature, as quasiquotes expand to code referencing scala.meta.trees.Origin which does not exist in 4.8.x.

This means that Scalafix rules containing quasiquotes compiled against scalameta 4.9.x will cause link errors if ran on older Scalafix versions. As a result, we need a minor Scalafix bump when taking that in, despite the fact that it's "just" a minor bump in a SemVer lib (we could argue that a major bump of scalameta was needed, but backward compatibility guarantees with macros is not very well defined).

bjaglin avatar Feb 10 '24 17:02 bjaglin

6d8b555147fdab3d001fc24411dabb237bde6512 causes core compilation to succeed, but docs2_13 to fail

[error] Caused by: java.lang.ClassNotFoundException: scala.meta.trees.Origin

That's because for some reason, coursier prefers 4.8.15 over 4.8.15+150-a7c0baa0-SNAPSHOT there:

sbt:scalafix> show docs2_13/evicted
...
[info] 	* org.scalameta:scalameta_2.13:4.8.15 is selected over {4.8.15+150-a7c0baa0-SNAPSHOT, 4.8.15+150-a7c0baa0-SNAPSHOT, 4.8.15+150-a7c0baa0-SNAPSHOT, 4.8.15+150-a7c0baa0-SNAPSHOT
[info] 	    +- org.scalameta:mdoc_2.13:2.5.2                      (depends on 4.8.15)
[info] 	    +- org.scalameta:mdoc-cli_2.13:2.5.2                  (depends on 4.8.15)
[info] 	    +- org.scalameta:semanticdb-scalac-core_2.13.12:4.8.15+150-a7c0baa0-SNAPSHOT (depends on 4.8.15+150-a7c0baa0-SNAPSHOT)
[info] 	    +- ch.epfl.scala:scalafix-core_2.13:0.11.1+108-789b602c-SNAPSHOT (depends on 4.8.15+150-a7c0baa0-SNAPSHOT)

Adding scalameta at the root does affect resolution, so it looks like Coursier is following nearest-win instead of latest-win (despite what's expected).

 lazy val docs = projectMatrix
   .in(file("scalafix-docs"))
   .settings(
+    libraryDependencies += scalameta,
sbt:scalafix> show docs2_13/evicted
...
[info] 	* org.scalameta:scalameta_2.13:4.8.15+150-a7c0baa0-SNAPSHOT is selected over {4.8.15, 4.8.15}
[info] 	    +- ch.epfl.scala:scalafix-docs_2.13:0.11.1+108-789b602c+20240211-1152-SNAPSHOT (depends on 4.8.15+150-a7c0baa0-SNAPSHOT)
[info] 	    +- ch.epfl.scala:scalafix-core_2.13:0.11.1+108-789b602c+20240211-1152-SNAPSHOT (depends on 4.8.15+150-a7c0baa0-SNAPSHOT)
[info] 	    +- org.scalameta:semanticdb-scalac-core_2.13.12:4.8.15+150-a7c0baa0-SNAPSHOT (depends on 4.8.15+150-a7c0baa0-SNAPSHOT)
[info] 	    +- org.scalameta:mdoc_2.13:2.5.2                      (depends on 4.8.15)
[info] 	    +- org.scalameta:mdoc-cli_2.13:2.5.2                  (depends on 4.8.15)

Forcing eviction via ea2e835ecdb817268bc963a4093d7913daed8498

bjaglin avatar Feb 11 '24 10:02 bjaglin

ea2e835ecdb817268bc963a4093d7913daed8498 exposes an incompatibility between mdoc and the latest scalameta SNAPSHOT

[error] Caused by: java.lang.ClassNotFoundException: scala.meta.internal.prettyprinters.enquote$

Following-up in https://github.com/scalameta/mdoc/pull/842

bjaglin avatar Feb 11 '24 11:02 bjaglin

[info] warning: patch.md:168:22: local val dialectOnly$macro$4 in value qual$12 is never used
[info] Patch.removeImportee(importee"Future").showDiff()
[info]                      ^^^^^^^^

Following-up in https://github.com/scalameta/scalameta/issues/3546

bjaglin avatar Feb 11 '24 12:02 bjaglin

[info] error: patch.md:168:1: token not found: 
[info] Patch.removeImportee(importee"Future").showDiff()
[info] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[info] java.util.NoSuchElementException: token not found: 
[info] 	at scalafix.util.TokenList.$anonfun$tok2idx$2(TokenList.scala:27)
[info] 	at scala.collection.immutable.Map$WithDefault.default(Map.scala:181)
[info] 	at scala.collection.MapOps.apply(Map.scala:176)
[info] 	at scala.collection.MapOps.apply$(Map.scala:175)
[info] 	at scala.collection.AbstractMap.apply(Map.scala:405)
[info] 	at scalafix.util.TokenList.leading(TokenList.scala:15)
[info] 	at scalafix.internal.patch.ImportPatchOps$.remove$1(ImportPatchOps.scala:229)
[info] 	at scalafix.internal.patch.ImportPatchOps$.$anonfun$superNaiveImportPatchToTokenPatchConverter$34(ImportPatchOps.scala:264)
[info] 	at scala.collection.StrictOptimizedIterableOps.map(StrictOptimizedIterableOps.scala:100)
[info] 	at scala.collection.StrictOptimizedIterableOps.map$(StrictOptimizedIterableOps.scala:87)
[info] 	at scala.collection.mutable.LinkedHashSet.map(LinkedHashSet.scala:34)
[info] 	at scalafix.internal.patch.ImportPatchOps$.superNaiveImportPatchToTokenPatchConverter(ImportPatchOps.scala:264)
[info] 	at scalafix.internal.patch.PatchInternals$.treePatchApply(PatchInternals.scala:118)

https://github.com/scalacenter/scalafix/blob/61dce03ff6f6513e0b275dba72a935615099b2f4/scalafix-core/src/main/scala/scalafix/internal/patch/ImportPatchOps.scala#L203 brings false negatives for quasiquotes-built trees since https://github.com/scalameta/scalameta/pull/3450, resulting in an exception instead of the documented no-op.

Another similar guard is impacted, although it causes a slight regression that might not be worth fixing: https://github.com/scalacenter/scalafix/blob/61dce03ff6f6513e0b275dba72a935615099b2f4/scalafix-core/src/main/scala/scalafix/patch/Patch.scala#L103

  • Patch.replaceTree(q"foo", "bar") is no-longer a no-op as the early-return no longer applies now that quasiquotes generate trees with positions
    • It is now the same as Patch.addLeft(q"foo", "bar") or Patch.addLeft(Term.Name("foo"), "bar") (unchanged behavior for them): it adds a leading string to any tree, as the BOF token has the same hash no matter the origin, causing a false positive
  • Patch.replaceTree(Term.Name("foo"), "bar") remains a no-op thanks to the early-return

bjaglin avatar Feb 11 '24 17:02 bjaglin