-
Notifications
You must be signed in to change notification settings - Fork 5
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
Dynamically loaded plugins #41
Comments
I'm a big supporter and frequent user of Metals, and I'd love to see the tool grow to become the de facto language server for Scala. One of the things that could help facilitate this is having the ability to extend Metals in new ways as dictated by the requirements of businesses, without invasively modifying any code. A plug-in architecture would be a welcome addition and help cement Metal's role in the future of the Scala programming language. |
If this is considered a valuable direction, we could put together a pull request. |
Thank you for reporting! Can you please provide more examples of functionality in Metals that you would like to extend with plugins? The benefit of built-in integrations over plugins is that we can ensure the built-in integrations work consistently and play nicely with each other. Composing plugins is a hard problem. LintingI am on the fence about allowing plugins to report custom diagnostics since I think compile error in Metals should always reflect compile errors in the build. Both Wartremover and Scapegoat already work out-of-the-box with Metals since they are compiler plugins and we report diagnostics from the compiler. For linters like Scalafix and Scalastyle, my idea so far has been to implement custom integrations in the Metals codebase.
I would prefer to discuss how to enrich the Scalafix API to enable your more advanced use-case. I estimate it wouldn't require a large change in Scalafix to allow rules to inspect several files simultaneously. A lot of design work is required to implement a rich semantic API, we should strive for a solution that makes it possible to run those analyzers inside Metals as well as build tools (sbt, gradle, maven, pants, ...) so they can be enforced in CI. Code formattingI would be happy to merge a PR that adds an integration with, for example, Scalariform. The benefit of this approach is that we can code review the Scalariform integration to make sure it works as smoothly as the Scalafmt integration. RefactoringOnce refactoring support is implemented, my idea so far has been to build on top of Scalafix in a similar way as with linting. Some more design work is required to enable IntelliJ-style inspections (example: convert single line string to multiline |
We could also do plugins as extensions to LSP - similar to TreeViewModel one. So each plugin would provide additional methods based on the information Metals provide. Although I agree that we should most likely keep everything with Metals and we can enable certain plugins by settings. |
Examples:
This is a good argument for errors being reproducible in the build. Are compiler plug-ins the only way to generate build failures that can be used by Metals?
The problem that I see it is that some linters depend on what tools you are using (Spring, JDBC, Spark, etc.), and others depend on personal preferences (e.g. functional Scala). Personally, I want to lint purely functional Scala. I don't think that would be great to push on other users. How would you suggest doing that without a Metals plug-in of some kind?
Control flow analysis in Scalafix would be awesome. @vovapolu Do you have anything you could share / show with @olafurpg? |
At the moment yes. After #7, it will also be possible generate custom compile errors in Metals and the build with custom Scalafix rules.
Scalafix already has a plugin architecture that allows people to implement their own code analyzers that report diagnostics along with optional auto-fixes https://scalacenter.github.io/scalafix/docs/developers/tutorial.html. The way I see people using this in Metals is that they update their
This configuration would be picked up by Metals and sbt-scalafix as well as any other Scalafix build tool integrations for Maven, Gradle, Mill, .. |
@jdegoes @olafurpg // NastyFunction.scala
object NastyFunction {
def usePrintln(foo: String) = {
println(foo)
}
} // MyBeautifulCode.scala
object MyBeautifulCode {
def myFunc = {
NastyFunction.usePrintln("Hello world") // desirable error
}
} And here is everything becomes complicated. I need to store information about such properties and update it. In IDE I need to update it incrementally in order to provide quick response. Another problem is memory -- with a sufficiently large number of analyzing files (in IDE or other tool like some CLI) we can't store all that info in memory, we need to cache it on the hard disk. I doubt that the Scalafix should solve such problems. But it can be very helpful in analyzing the dedicated files and providing information that later will be stored in memory and hard disk. I see some similar ideas in metals and overall I feel SemanticDb is the way to the same direction. But now I can't describe the generic and elegant solution for flow analysis without hardcoding logic to the metals fork or some kind of plugins for metals. Probably some work should be done both from Scalafix side and metals. @olafurpg What do you think? If there's some existing solution for problems I've described can you show me it? I did not fully understand some parts of metals yet. |
@olafurpg As the temporary solution for the current topic can we give users a way to use metals forks in their editors (at least in the vscode as the most popular editor)? In vscode there's a setting to manually set up metals version, we could allow to set up organization with some nasty warning ( |
@olafurpg Any thoughts about flow control or providing access to metals forks in the editors? |
I believe it's possible and desirable to extend Scalafix to support inter-project and inter-file analysis. I don't have a design proposal at the top of my head but I'm open for suggestions. I agree it's important to take into account incremental analysis so the Scalafix rules could be used in the context of an IDE such as Metals. For running forks of Metals, the VS Code extension already supports providing a custom Metals version as well as adding custom repositories for resolution. Have you tried publishing a fork of Metals under the |
Closing this feature request as a wontfix. See #41 (comment) for more details.
@vovapolu I'm happy to continue the discussion in the Scalafix issue tracker for enabling incremental analysis across multiple files. I'm also happy to merge PRs that refactor Metals internals to easier to extend with new functionality. |
Is your feature request related to a problem? Please describe.
There's no way to extend Metals functionality for now, except only by hardcoding it into a custom fork of the code base. The problem is one of modularity—we can't augment functionality of the language server in an easily maintainable way.
In the long run, it will be beneficial for users and the whole tooling community if users can extend and customize Metals with functionality of their choosing.
Describe the solution you'd like
I'd like the ability to add dynamically-loaded plugins. One of the possible solutions is SIP that loads JARs implementing some plugin interface.
I haven't yet studied the Metals codebase enough to describe the general plugin interface I'd like, but I have some thoughts:
didChange
,didOpen
and etc.), but I assume there will be additional events specifically for Metals and for Scala-related events.scalafmt
andscalafix
. There is no need to implement any part of Metals with plugins, but the functionality required to implement Scalafmt and Scalafix as plugins would give a very good idea of what a plugin interface should look like. Scalafmt is a good example for a plugin, because it's not deeply connected with internals of the language server and it performs only one function— formatting the code. Scalafix also performs quite unique and discrete functions, and at the same time has more intersections with other popular projects in terms of linting, for example. (https://github.com/wartremover/wartremover or https://github.com/sksamuel/scapegoat).I could see some users may want to use one of those with extended support in the IDE. Of course, my thoughts about
scalafmt
andscalafix
are purely hypothetical, they aren't listed here only as examples or thought experiments.Describe alternatives you've considered
I don't thinks there are alternatives for the idea of plugins for Metals, but I've thought of some alternatives for my specific case that can show the necessity for plugins.
I'm developing code analysis tool, and for my specific case I have considered two options: compiler plugin and Scalafix rules. Both of them lack the ability to perform flow control of the source code, e.g. inspecting semantic and syntactic information for several files simultaneously.
The next big problem here is to do it incrementally, load and save intermediate info for only some files depending on what files were changed, how often they are changing and how these files are connected.
I feel such functionality can be implemented only on IDE level.
Search terms:
plugin, linting, code analysis, modularity
The text was updated successfully, but these errors were encountered: