-
-
Notifications
You must be signed in to change notification settings - Fork 353
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
Exclude folders bsp #3329
Exclude folders bsp #3329
Conversation
Thanks for the PR! Given the topic at hand, I wonder if @jastice has any opinions here on what's the right way to do things. He's the author of BSP on the intellij side, and would likely know more than me the limitations, potential workarounds, and expected future development of the IntelliJ BSP client |
Forwarding to @AnthonyGrod who is currently working on integrating Mill with the new IJ BSP plugin |
Hello, at the moment I'm focusing on very basic functionalities of Mill over IntelliJ-BSP plugin integration, but I'll be happy to help when I will finish the basic support. |
@pawelsadlo can you explain in the PR description how your solution works? |
@lihaoyi wrote a description, if anything needs elaboration, tag me |
Thanks! Will take a look. @lefou should probably review this too since he's more familiar with the BSP side of things |
At a quick glance this looks reasonable to me |
path.last.startsWith(".") || | ||
path.endsWith(os.RelPath("out")) || | ||
path.endsWith(os.RelPath("target")) || | ||
path.endsWith(os.RelPath("docs")) || |
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.
Why are we ignoring docs/
? I'm not aware of such a folder name being treated specially by any build tool
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.
Those are patches ignored during the os.walk in the search of build.sc files (so basically a subprojects), I assumed that we don't expect a subproject to bo located inside docs directory.
The logic is:
- We recursively search for build.sc files under top level root of our project. (Directories containing build.sc are potential directories where out, .idea, .bsp , .bloop would be generated).
I search for build.sc instead of .idea, out, .bsp and .bloop because the latter may not be present at the time of bsp import, and may appear later (for example during build of subproject) - We exclude .bsp,.idea,.bloop,out from folders of found in step 1.
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 still think we try to fight a symptom of a bad behaving BSP client here. BSP is about declaring what makes a project, not what-not makes a project. If the BSP client (the IDE) handles more than that, we simply can't and shouldn't control that via BSP.
Hence, I don't think I can properly review this PR, as I don't agree on it's purpose.
def additionalExclusions = projectsRootPaths.flatMap { path => | ||
Seq( | ||
outputPathItem(path / ".idea"), | ||
outputPathItem(path / "out"), | ||
outputPathItem(path / ".bsp"), | ||
outputPathItem(path / ".bloop") | ||
) | ||
} |
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'm not convinced excluding hardcoded directories is the right approach for a generic protocol. Esp. since some of these directories aren't even created or managed by us.
@pawelsadlo can you point out where in the code we set the excluded folders to be marked as excluded in BSP, and therefore in IntelliJ? I've been trying to ready through the code and haven't figured out how it works, although testing it out it does the right thing @lefou I think we should do a best-effort here. It's not super elegant, and maybe it should be the IDE's responsibility to read the gitignore file and ignore folders. IntelliJ actually does have that functionality, but it's not automatic (you have to navigate to gitignore and click click), and it doesn't seem fully functional (e.g. it doesn't help you exclude |
def ignore(path: os.Path): Boolean = { | ||
path.last.startsWith(".") || | ||
path.last == "out" || | ||
path.last == "target" | ||
} |
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.
@pawelsadlo rather than hardcoding things here, and below in additionalExclusions
, let's use the .gitignore
. We can use JGit to perform these git check-ignore
checks quickly without the subprocess overhead using the classes from org.eclipse.jgit.ignore.*. We'd also need to check the equivalent of git ls-files
(e.g. TreeWalk) to see if the folder has been added to the index, since folders explicitly added to the git index bypass the gitignore. That will generalize this to support everything that is gitignored, which is probably what a developer working with an arbitrary git codebase wants.
Special-casing git
should be the right thing for 99% of developers who use Git for version control today. If .gitignore
is not present, we can fall back to only ignoring the top-level out/
, .idea/
, and .bsp/
folders. I don't think we should traverse recursively and try to find stuff in subfolders.
It's possible someone will come in future asking for hg
integration or something, but we can cross that bridge when we get to it
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.
Of course ,however I am on vacation now, I will do this as soon as I have access to my laptop.
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.
Sure! no hurry
@pawelsadlo can you also manually test to verify that generated source files inside the excluded |
sanitizeUri(path) + "/", | ||
OutputPathItemKind.DIRECTORY | ||
) | ||
def additionalExclusions = projectsRootPaths.flatMap { path => |
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.
@lihaoyi these folders are excluded ones, they then are sent to bsp by buildoutputpaths
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.
Got it. Is everything in buildTargetOutputPaths
considered excluded?
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.
Formally, according to BSP docs it's BSP client decision what to do with buildOutputPaths response from BSP server. most of clients are excluding them, in particular intellij.
What's more ,in case of intellij there are the limitations I mentioned in the PR description (these are not formalized though ,it's just what I have observed by reading through intellij bsp source code and confirmed by testing )
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.
Got it. Can you also manually test VSCode+Metals to see what the behavior is there? Just so we know what affect this PR will have on those users (if any)
Sure |
@pawelsadlo just bump on this :) if you don't have the time to continue, I can pay out half the bounty and finish off the PR myself |
@lihaoyi I'm ok with half of bounty , I'll be busy next week anyway, so can't do it soon. |
I took over the PR and removed the Manually tested with normal Scala and Java projects with root module, without root module, and with meta-build. All seem to work, with navigation intact in all source and build files and the |
@pawelsadlo can send me an email with your bank transfer details and i can close out the bounty |
@lihaoyi sent you the details |
fixes #3015
There are several limitations implied by
intellijBSP
client which led to this implementation:mainly:
content root
akabaseDirectory
(at least I didnt find a way - excluding.bsp
is hardcoded inintellijBSP
).Intellij
won't include content root of module if it has no sources defined (this might be a bug inintellijBSP
).This implies that there should be at least one module which content root is equal to project root.
In some sitiations such module is defined by user in
build.sc
, but not always.In other cases, a
SyntheticRootBspBuildTargetData
withbspTarget.baseDirectory
==topLevelProjectRoot
would be created to handle exclusions.I went for a solution that is very local to
bsp
module.Alternative solutions I though about:
RootModule with BspModule
either during bootstrap if there is no module withBspTarget.baseDirectory
=topLevelProjectDirectory
RootModule with BspModule
in bspWorkerState
However personally I think that alternative solutions seem overkill for achieving such simple effect as excluding directories.
How it works:
MillBuildServer.State
contains additional field -Option[SyntheticRootBspBuildTargetData]
SyntheticRootBspBuildTargetData
contains minimal data required forBuildTarget
to be reported bydef workspaceBuildTargets
(forced by limitation 1).Some
only if there is no normal module withBspBuildTarget.contentRoot
==topLevelProjectRoot
aka. module which can exclude topLevel folders
SyntheticRootBspBuildTargetData
is created, it is reported indef workspaceBuildTargets
together with other modules, but filtered out from other bspClient requests (exceptions:buildOutputPaths
, andbuildTargetSources
)def buildTargetOutputPaths
- for a module which hasBspBuildTarget.contentRoot
==topLevelProjectRoot
(so potentiallySyntheticRootBspBuildTargetData
) ios.walk
fromtopLevelProjectRoot
looking forbuild.sc
files and in their folders I exclude ".idea",".bsp","out",".bloop". - os.walk ensures exclusion of folders in nested mill projectsnote: following paths are excluded from walk
Actually if there was no limitations I mentioned, this would be the only required step.
5. Because of
limitation 2
i had to report some source forSyntheticRootBspBuildTargetData
- chosen "src", but this can be any, even non existing path.Tested manually: