-
Notifications
You must be signed in to change notification settings - Fork 82
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
Scala 3 support #466
Scala 3 support #466
Conversation
Makes it easier to work in the build.
Previously, mdoc didn't support Scala 3 when processing markdown files, it only supports Scala 3 worksheets. This commit adds support to additionally process markdown files with Scala 3. This is still a work-in-progress. Scala 2 tests are still passing and the Scala 3 build *compiles* but tests fail.
fail proper this time.
The positions coming from Scala 3 parser are empty. We used it before Scala 3 dialect for scalameta parser was finished. Do let me know if you need any help with Scala 3 part, that was mostly done by be 😅 |
Thanks @tgodzik I sort of took a stab at it almost mechanically, now it's the hard part. I still need to figure out @olafurpg's changes to cli module (whether they're supposed to go out?), as they introduce metaconfig's scala 2 macros and don't work for me locally. What I'm trying to figure out is if I'm missing something :D So just to clarify:
I should've clarified those before starting with this :) |
@olafurpg might know more.
Do you mean scalameta parser? Semanticdb is not used here as far as I know.
We would most likely need to add that to use scalameta parser, but we do have those conversions for Scala 2, so this should be something similar.
Yeah, if we use scalameta parser the only thing that needs to stay are separated |
The cli module will need to stay on 2.13 because it uses macros.
|
Ok awesome, I'll then take another stab at this over the weekend to get it into a working state hopefully, unless I hit another blocker. |
Ok @olafurpg @tgodzik I had to make everything worse to make it better :D
So in the current state, the build and cross-sources must be configured correctly to move on to just fixing the tests and potential bugs. Therefore my proposal is:
|
build.sbt
Outdated
lazy val fs2Version = Def.setting { | ||
if (scalaVersion.value.startsWith("2.11")) "2.1.0" | ||
else if (scalaVersion.value == "3.0.0-M2") "2.5.0" | ||
else "2.5.3" | ||
} | ||
|
||
lazy val munitVersion = Def.setting { | ||
if (scalaVersion.value == "3.0.0-M2") | ||
"0.7.21" | ||
else V.munit | ||
} | ||
|
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.
Previously tests weren't running on Scala 3, so we didn't have to cherry pick versions.
The proposed plan sounds great. It’s good to separate the structural changes from fixing the tests. |
Another yak that I've just realised: CLI tests have no chance of passing on Scala 3 unless some form of args processing takes place - at the moment it's just returning default settings (because no derivation), and the CliSuite tries to process the entire docs folder. So my questions are:
|
I'm probably confused then - in Olaf's original PR, Are you proposing an inverse relation? |
I haven't looked closely at the PR 😓 , but cli seems to be build only for scala 2 versions. Was that working? I think the plan was not to build it for Scala 3. If it's impossible to reverse the relation (cli do depend on mdoc), we could put everything cli related into |
For sure we could CLI tests into scala-2 directory and run it only for Scala 2. |
I hope Olaf can shed light :D Will take a closer look tomorrow at what interface is passed through between cli and mdoc (MainSettings?) and perhaps I just did something silly and misunderstood how the two are separated. |
Overall, I think MainSettings will just not work for Scala 3. we either need to migrate metaconfig to Scala 3 (in that case only 3.0.0-RC2 would be enough) or switch to a separate configuration library (something like sconfig for example). The same problem exists in scalafix scalacenter/scalafix#1316 |
I would oppose switching metaconfig with sconfig. My long-term plan is to replace metaconfig with Scalameta/moped but neither of those projects currently support Scala 3. If there’s any effort to upgrade the macros for Scala 3 then it should ideally happen in Moped, but it’s not something I expect will happen in the near future. The cli module can compile with 2.13 and be used from 3. This was working in my original mdoc PR making the build compile with Scala 3. There are maybe some issues with this approach if users have both sourcecode 2.13/3 on their classpath but it should be fixable. |
UPDATE: it was necessary to set 2.13 on cli explicitly 🤦 that was some days lost :D According to compatbility guide it should work, yep. I got thrown off because locally when I run
And I got the same on your branch.. I've removed scala 3 from cli and pushed, will see if it behaves differently on CI. |
|
||
class MdocPropertiesSuite extends FunSuite { | ||
test("default") { | ||
val obtained = MdocProperties.default(PathIO.workingDirectory).scalacOptions | ||
|
||
if (BuildInfo.scalaVersion.startsWith("3.0")) | ||
if (mdoc.internal.BuildInfo.scalaVersion.startsWith("3.0")) |
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.
FYI, I've found it very helpful to create custom MUnit tags to skip tests based on the Scala version. See https://github.com/scalameta/munit/blob/35d868403aca0e71b31b8a794472ddcbee370334/tests/shared/src/test/scala/munit/BaseSuite.scala for an example of how it's used in the MUnit codebase
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.
We have similar tags in the cross tests in Metals also.
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.
This has been a lot of work! Thank you @keynmol for this contribution. It's fantastic to see that mdoc will soon be able to support Scala 3.
The magic import tests in FileSuite
aren't that important to support in Scala 3. Internally, mdoc kind of has ammonite-style scripting support excluding incremental compilation and several other caveats. I never got around to fully polish that functionality into a publicly documented feature. It's totally fine to run those tests only in Scala 2.
I would recommend using MUnit tags to skip failing tests in Scala 3 and then merge this PR before the diff gets any bigger!
mdoc/src/main/scala-3/mdoc/internal/markdown/Instrumenter.scala
Outdated
Show resolved
Hide resolved
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.
Great work! I think it's almost finished, I left some comments/questions.
@@ -10,7 +10,7 @@ import scala.meta.inputs.Input | |||
import scala.meta.io.AbsolutePath | |||
import scala.collection.JavaConverters._ | |||
import scala.meta.io.RelativePath | |||
import mdoc.internal.pos.PositionSyntax._ | |||
// import mdoc.internal.pos.PositionSyntax._ |
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.
Let's remove this one if it compiles
|
||
val scala = | ||
if (BuildInfo.scalaBinaryVersion.startsWith("3.0")) | ||
Scala3.withAllowToplevelTerms(true).withAllowToplevelStatements(true) |
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.
withAllowToplevelStatements
is true by default.
|
||
class MdocPropertiesSuite extends FunSuite { | ||
test("default") { | ||
val obtained = MdocProperties.default(PathIO.workingDirectory).scalacOptions | ||
|
||
if (BuildInfo.scalaVersion.startsWith("3.0")) | ||
if (mdoc.internal.BuildInfo.scalaVersion.startsWith("3.0")) |
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.
We have similar tags in the cross tests in Metals also.
|val xx = fn | ||
| ^^ | ||
| ^ |
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.
We worked around the issue, because this was causing issues for edit distance. If it's on a non-existing position we cannot match it to any real token. #386
@@ -18,7 +18,7 @@ jobs: | |||
steps: | |||
- uses: actions/checkout@v2 | |||
- uses: olafurpg/setup-scala@v10 | |||
- run: sbt docs/mdoc | |||
- run: sbt '++2.12.13 docs/mdoc' |
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.
Isn't this the default version?
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.
It no longer is - I had to set 2.13 to be the default for the "Scala 3 module depending on 2.13 module to work"
Here's the failure: https://github.com/scalameta/mdoc/runs/2331363147#step:4:256
cli
module is a dependency of mdoc
, which is a dependency of docs
and it needs to be on 2.12 for I guess reusing the SBT plugin code
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 still necessary after #493? Evilplot has 2.13 releases on Sonatype
|val xx = fn | ||
| ^^ | ||
| ^ |
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.
Could you open up an issue to figure it out later on?
Issue opened for the token matching issue: #485 |
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 left some more comments, but I think we are close to finishing. @keynmol do you need any help with it? We can always merge as is and try to improve things later on as long as Scala 2 functionality remain. What do you think?
@@ -99,8 +110,9 @@ class ScalacOptionsSuite extends BaseCliSuite { | |||
onStdout = { out => assert(!out.contains("discarded non-Unit value")) } | |||
) | |||
|
|||
// TODO: fix for Scala 3 |
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.
Does the flag even work for Scala 3? We can create a follow up issue.
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.
It does exist but it doesn't seem to do anything in REPL - is it the TPrint that prints out the type?
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.
For Scala 3 it's based on macros. It's not the TPrint as in case of Scala 2
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.
It's OK to remove the TODO
comment. It's already explicitly documented that this test is skipped in Scala 3. If it's important to fix this test then it's better to open an issue and link to the issue from here
@@ -111,6 +116,14 @@ class MarkdownCompiler( | |||
report(vreporter, input, fileImports, run.runContext, edit) | |||
} | |||
|
|||
class CollectionReporter extends dotty.tools.dotc.reporting.Reporter { |
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.
Can we use FilterStoreReporter ?
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.
Looking at it - it seems to be implemented in terms of Scala 2 models, do you mean this one? https://github.com/scalameta/mdoc/blob/main/mdoc/src/main/scala-2/mdoc/internal/markdown/FilterStoreReporter.scala (and its version specific variations)
I had to create this one because (trying to reconstruct from memory) because I was getting NPE from the built-in one and for warning tests I needed all the diagnostics, and by default only errors are surfaced
Yep - that's why I didn't unify things like instrumenter - to avoid breaking the Scala 2 versions, and combine them in a later issue. |
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 we should merge it and fix the rest of the issues in separate PRs. I don't see anything really blocking here. @olafurpg what do you think?
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.
@@ -18,7 +18,7 @@ jobs: | |||
steps: | |||
- uses: actions/checkout@v2 | |||
- uses: olafurpg/setup-scala@v10 | |||
- run: sbt docs/mdoc | |||
- run: sbt '++2.12.13 docs/mdoc' |
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 still necessary after #493? Evilplot has 2.13 releases on Sonatype
@@ -12,6 +12,6 @@ jobs: | |||
fetch-depth: 0 | |||
- uses: olafurpg/setup-scala@v10 | |||
- uses: olafurpg/setup-gpg@v3 | |||
- run: sbt docs/docusaurusPublishGhpages | |||
- run: sbt '++2.12.13 docs/docusaurusPublishGhpages' |
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.
Ditto, evilplot
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.
Ah, I think I got it now.
- We need 2.13 to be the default version in the build for the
Scala 3 module -> dependsOn Scala 2.13 module
to work 2.12
is needed in docs specifically because it depends on theplugin
which cannot be built for 2.13 (SBT)
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.
Hmm, why does the docs project depend on the sbt plugin? The plugin is enabled in the docs project but there shouldn’t be a project dependency there 🤔
either way, feel free to ignore this comment
import java.io.PrintStream | ||
|
||
class CodePrinter(ps: PrintStream, baseIndent: Int = 0, baseNest: Int = 0) { | ||
private def indent = " " * (baseIndent + nestCount) |
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.
What happens if the user has 3-space indent?
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 user gets punished for being different!
Well, actually it doesn't seem to affect the nesting:
=> Obtained
"""|```scala
|val x = 25
|// x: Int = 25
|def test =
| println(x + 1)
| if x > 25 then
| println("yep")
| else
| println("nope")
|test
|// 26
|// nope
|```
|
|```scala
|def test =
| println("howdy!")
|
|test
|// howdy!
|```
|""".stripMargin
=> Diff (- obtained, + expected)
-```scala
-val x = 25
-// x: Int = 25
-def test = ∙
- println(x + 1)
- if x > 25 then
- println("yep")
- else
- println("nope")
-test
-// 26
-// nope
-```
∙
-```scala
-def test =
- println("howdy!")
-
-test
-// howdy!
-```
Is this what you had in mind? If so, I can commit this test as a separate Scala3-specific spec
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.
Pushed the test in 2198002
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.
Looks good. Always worth having tests like these
@@ -99,8 +110,9 @@ class ScalacOptionsSuite extends BaseCliSuite { | |||
onStdout = { out => assert(!out.contains("discarded non-Unit value")) } | |||
) | |||
|
|||
// TODO: fix for Scala 3 |
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.
It's OK to remove the TODO
comment. It's already explicitly documented that this test is skipped in Scala 3. If it's important to fix this test then it's better to open an issue and link to the issue from here
@@ -231,7 +355,7 @@ class NestSuite extends BaseMarkdownSuite { | |||
) | |||
|
|||
checkError( | |||
"implicit-nok", | |||
"implicit-nok".tag(SkipScala3), |
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.
This could be worth commenting next to the test.
After lots of printlns I realised there was a custom scalameta-like parser for Scala 3.
All of the positions in sections had
Input.None
, so slicing wasn't working - making all tests fail.I've added a few things on top of #443 (didn't realise it was in a fork), and now I seem to be getting
On the 3.0.0-M3 tests. Some of them are super easy to fix (different wording error messages in Scala3), I'll take a look at the rest which might be more complex.