-
-
Notifications
You must be signed in to change notification settings - Fork 372
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
Decouple the Scala version used by Ammonite from the one exposed to users #1135
Decouple the Scala version used by Ammonite from the one exposed to users #1135
Conversation
That makes it easier later on to extract a Java interface for CompilerLifecycleManager
Either has less cases to handle, which makes the extraction of a Java interface for CompilerLifecycleManager more straightforward.
Having it rely on Frame from ammonite.repl.api, rather than a concrete Frame implementation, makes it easier to extract an interface for CompilerLifecycleManager later on.
This change doesn't change the semantic of this logic. It makes easier to adapt this method to the upcoming Java-based Preprocessor API.
…and remove Compiler.parse This allows to strip the Compiler public API of references to scala.tools.nsc. Later on, makes it easier to extract a Java interface for Compiler.
This makes it more straightforward to extract a Java API for parsing later on.
Just like the previous commit, this facilitates extracting a Java API for parsing later on.
colors is only useful from the REPL, not from scripts. It makes more sense that it lives in ReplAPI.
util will be a shared dependency of runtime / interp on the one hand, and the upcoming compiler module on the other. Moving Classpath here allows it to be used by both.
The clipboard stuff can live entirely in user space, there's no need to have its calls cross the userspace <-> Ammonite internals barrier. Later on, this is helpful to Java-ize ReplAPI.
That makes it easier to Java-ize InterAPI. It should be do-able to add back os-lib stuff later on.
util should need to be cross-compiled for all supported Scala versions, including the upcoming Scala 3. Dropping the ops dependency allows not to have to cross-compile ops.
It seems it's unused.
Just like for util <-> ops, repl-api is meant to be cross-compiled to all supported Scala versions. Removing the dependency towards ops allows not to cross-compile ops.
That makes it more straightforward to Java-ize InterpAPI later on.
That makes it easier to Java-ize ReplAPI later on.
When creating a compiler instance, Ammonite passes it two class paths: the "initial" one, and the main one. The former is subject to whitelisting when --thin is passed, not the latter. Later on, when adding --scala-version, there can be JARs used internally by Ammonite that are in both paths. Their classes need to be blacklisted, but these JARs should still be loaded via the main class path, as any other JAR added by users. Before this commit, we were naively removing from the main class path any JAR already in the initial class path, which was a problem for the JARs in both paths mentioned above.
ForkClassLoader injects resources from another ClassLoader. When --thin is passed, it could have injected resources that should have been blacklisted. Alternatively, maybe we could have adde a whitelisting layer on top of it too…
A few things are not whitelisted anymore after removing the ops dependency here or there. Whitelisting in these tests will be added back when decoupling the Ammonite and user-facing Scala versions.
8269d06
to
87e7341
Compare
87e7341
to
26ddbcf
Compare
It gets thrown by users, with their own Scala version, and later caught by Ammonite with its own Scala version. So it needs to be put in a shared Java API, so that AmmoniteExit is loaded by the same ClassLoader for both users and Ammonite alike.
The Java module is meant to be used by users and Ammonite at the same time via the same class loader. The Scala module is meant to be loaded on the fly in the user ClassLoader, depending on which Scala versions users want to use.
This simplifies the conversion of this class to a Java interface (single method instead of two, and no explicit collection).
This changes InterpAPI from a Scala class to a Java class. For this to work, some of the methods of InterpAPI get more Java-compatible signatures. In particular, mutable collections become java.util.List. In order to recover the ease of use of the Scala signatures and collections, we add extension methods, defined in InterpBridge.InterpAPIExtensions, so that most former Scala methods can still be used with InterpAPI.
TestBridge lives in "user space" in some tests. It needs to be compiled with the user space Scala version, rather than the Ammonite Scala version. It's put in a dedicated module, and its class path is passed along the one of amm.compiler and amm.repl.api.full to the cross tests.
Just in case
The Ammonite and user Scala classes are not loaded by the same class loader in cross tests, so some comparisons have to be tweaked.
It seems these are needed for scala-xml to work in particular. Loading compiler plugins (which involves XML stuff) fails without this.
26ddbcf
to
9e402f2
Compare
The changes introduced by this PR are quite large… There are some breaking changes in the early commits (those changing The overall goal is to make Ammonite interact with the user session and scalac only via Java APIs, and this is achieved by adding Java interfaces, in new pure Java modules:
Extension methods, such as these or these, help make these interfaces more usable from Scala code. APIsThe original
|
To test
This publishes the modules that are loaded upon startup first ( |
To enable
Their Scala dependencies are:
All of them but fastparse / scalaparse / mainargs are already cross-published for mainargs for |
I'm hesitating discussing the various commits of this PR right now, or split it instead… @lihaoyi Just tell me if you're ok with the general direction, and feel like reviewing this (+4000 -2000 / 74 commits) PR or if you prefer me to split it in smaller PRs. |
Thanks Alex! I won't be able to get to this in the next few days, but hopefully have time coming up next week to give this a proper review |
I've come to realize that this PR actually deals with several successive concerns, even though things are not done in this order in the commit history:
It might be possible to add Scala 3 support with only the first step, even though I'd be in favor of keeping the others too (they would allow to stop cross-compiling most modules to So to help reviewing this, I could rebase things, and open a first PR only adding the |
Also, after the changes here, I feel the graph of modules in Ammonite becomes somehow messy… (
So that we would end up with just:
It could also be beneficial before the changes in this PR. In that case, we would end up with just:
(No more |
@lihaoyi If needed, I can be up for a call, if there are things you think would be more convenient to discuss this way. To clarify some of the stuff I said, it's probably too early for a thorough review… But I can split this PR in several ways, that can be reviewed / discussed successively, either by adding the |
FYI, I pushed the early Scala 3 support on this branch. Its README gives more details about what works / what doesn't work yet, and how to run Ammonite with Scala 3 support from the branch sources. |
Hey @alexarchambault! Sorry I just got to this. I think at a high level, I want to preserve the Regarding your earlier question splitting up the PR, I think limiting the first step to extracting a In general, let's aim to get Scala 3 in with minimal churn, and then we can consider further cleanups like dropping cross-compilation across Scala 2 versions later |
I think there's some overlap between the Java compiler interface you're trying to define and the one that metals uses: https://github.com/scalameta/metals/tree/main/mtags-interfaces/src/main/java/scala/meta/pc, maybe there's an opportunity for defining a common standard here? In Dotty we also have https://github.com/lampepfl/dotty/tree/master/interfaces/src/dotty/tools/dotc/interfaces which is very minimal but could be extended. |
Right. About
Yeah, that's what I'm going to do. We may even not need the Java API for |
@smarter Thanks for those links! It might be possible to extend those for Ammonite… The interfaces from metals seem quite specific to it though (with many lsp4j classes involved). But some definitions from the dotty interfaces could have been used here (like That said, for now, the level at which we abstract things in this PR involves things quite specific to Ammonite, like class whitelist stuff, the dependency completer, or even the handling of " |
Just so you know, I'll probably open a new PR adding just the new compiler module during the first week of January I think (so somewhere between Jan 4th and 8th - while still working on Scala 3 stuff based on this branch in a first time). |
Closing this. Going to open new PRs with less changes. |
This currently includes #1133, so it actually looks slightly lengthier than it is.
Checking what the CI says in a first time, I'll describe it in more details right after.