Skip to content
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

Invalid handling of nested build.sbt #695

Open
majk-p opened this issue Nov 15, 2024 · 3 comments
Open

Invalid handling of nested build.sbt #695

majk-p opened this issue Nov 15, 2024 · 3 comments

Comments

@majk-p
Copy link

majk-p commented Nov 15, 2024

Describe the bug

Metals plugin for nvim doesn't properly import projects that contain nested build.sbt. Consider following project structure:

.
├── build.sbt
├── LICENSE
├── modules
│   ├── library
│   │   └── src
│   │       └── main
│   │           └── scala
│   │               └── net
│   │                   └── michalp
│   │                       └── playground
│   │                           └── PlaygroundLib.scala
│   └── plugin
│       ├── build.sbt
│       ├── project
│       │   └── project
│       │       └── project
│       └── src
│           └── main
│               └── scala
│                   └── net
│                       └── michalp
│                           └── playground
│                               └── PlaygroundPlugin.scala
└── project
    ├── build.properties
    └── plugins.sbt

The important part is that there's build.sbt in the repository root as well as one in modules/plugin/build.sbt. The later is there for sake of defining plugin dependencies.

For full reproduction example see following minimal example project: https://github.com/majk-p/sbt-plugin-playground

It fails in vanila install of nvim + lazyvim

image

When the modules/plugin/build.sbt is removed, the plugin code is imported properly again:
image

Extra context

The example project is imported properly in VSCode
image
and in Zed
image

Expected behavior

Expected Metals in nvim to behave in the same way as with other editors.

Operating system

Linux

Version of Metals

v1.4.0

Commit of nvim-metals

f861db9

@ckipp01
Copy link
Member

ckipp01 commented Nov 16, 2024

Thanks for the report!

Expected Metals in nvim to behave in the same way as with other editors.

So this is the tricky part. The idea of a workspace in Nvim is sort of artificial. There is no "open this folder as the root of a workspace" like there is in other editors. Everything is just an open buffer. So nvim-metals sort of artificially needs to create a workspace by correctly identifying roots. As you can imagine, with the various buildtools and projects structures this gets very tricky to do in a reliable way. What I ended up defaulting to is that I do look for nested build files, but only one layer of nesting. So if you would have:

build.sbt
other/build.sbt

Then that's no issue. I don't go deeper than that by default because in a project that only has a single build.sbt you end up traversing down multiple levels and potentially finding things that are part of other projects on disk that you don't want. However, this situation has happened before so there is a find_root_dir_max_project_nesting setting that is defaulted to 1. You should be able to bump this to 2, and then it should work as expected for this project. Btw you can see the logic for how this all works in here.

@majk-p
Copy link
Author

majk-p commented Nov 18, 2024

Thank you @ckipp01, setting metals_config.find_root_dir_max_project_nesting = 2 helped!

Do you think it would be possible to have another strategy that would search for git repository in parents folder and default to the build.sbt found in the repository root?

@ckipp01
Copy link
Member

ckipp01 commented Dec 7, 2024

@majk-p so I want to avoid building this into nvim-metals. Mainly because for 95% of projects the default seems to work. For a workaround, you can use the find_root_dir_max_project_nesting. However, everything is configurable so in reality you can also override find_root_dir in your config and provide your own function that can do what you're suggesting so that it's always used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants