-
-
Notifications
You must be signed in to change notification settings - Fork 391
Goto dependency definition #3749
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
base: master
Are you sure you want to change the base?
Conversation
e2d17a7
to
6daf799
Compare
Thanks for your work! I'm glad to try this, If I compile cabal from master and compile HLS with this thread, everything should work then without any extra configruation? |
@July541 You're welcome! You do need to add |
I would say that the answer should be the same as "what do we do if gotoDefinition is called while a module has not yet been typechecked and it is in the shake build queue (or we're building dependencies, or whatever)?".
What happens if the cabal store gets corrupted and the interface files for a dependency get deleted? Presumably we will die horribly in some way? If so, I think it's fairly reasonable to die horribly here also.
I definitely think we should have some more tests. The one you described sounds good. It would be good to think of some weird situations and try to have tests for them. Quick brainstorming:
Any other weird cases people can think of?
So, if someone asks to go to a definition in a dependency and we don't have the IDE files, then we should definitely log something (or maybe even show a message?), but whatever we log and show could say that we're missing the IDE files and you can get them by doing X. Maybe that is a good enough UX? |
e05e50d
to
5cfb425
Compare
@michaelpj I am taking a stab at this test idea:
and as far as I can tell, different components within the same project are not allowed to depend on different versions of the same package. Am I missing something, or misunderstanding what you meant? |
They have to be independent, e.g. an executable component and a library component, something like:
|
(executables get their own build plan that doesn't necessarily have to be the same as the main build plan for the libraries, hence how this can happen!) |
@michaelpj Thank you for that clarification! |
@michaelpj I have tried making one component an executable and the other a library and cabal still seems to think that they depend on each other :( even when I don't specify either one as a dependency of the other. I have tried this for one cabal file and two cabal files. Both attempts can be found here: nlander@3c458b2. Is there something else that I need to add to allow the executable to have its own build plan? |
Okay, turns out I'm just wrong. I asked and the only things that get independent build plans are custom setups and build tools. And in practice it sounds like the only place this could happen is |
@michaelpj Thank you for double checking! |
@@ -31,7 +31,7 @@ runs: | |||
sudo chown -R $USER /usr/local/.ghcup | |||
shell: bash | |||
|
|||
- uses: haskell/actions/setup@v2.4.4 | |||
- uses: nlander/actions/setup@install-cabal-head |
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 try and get this upstreamed before we merge
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 waiting for a CI run to be approved for haskell/actions#290. If that passes I think it should be merged soon.
@@ -7,7 +7,7 @@ inputs: | |||
cabal: | |||
description: "Cabal version" | |||
required: false | |||
default: "3.8.1.0" | |||
default: "head" |
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.
Do we want to leave this here? Will we want to turn it back to a released version at some point? Write it down!
cabal.project
Outdated
source-repository-package | ||
type:git | ||
location: https://github.com/nlander/HieDb.git | ||
tag: 4eebfcf8fab54f24808e6301227d77ae64d2509c |
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's the status of the hiedb changes?
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.
@wz1000 what time frame were you thinking for merging my PRs?
-- project. Right now, this is just a stub. | ||
-- | Generates URIs for files in dependencies, but not in the | ||
-- project. Dependency files are produced from an HIE file and | ||
-- placed in the .hls/dependencies directory. |
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 in the project root? I guess maybe it needs to be so the LSP server thinks it's part of the project. It's a bit awkward to introduce a new directory just for this. Can we not put it in one of the existing places, like somewhere in dist-newstyle
?
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 you please elaborate a little about what you find awkward about generating a new directory? I don't think putting things in dist-newstyle
would be ideal because it's used by another tool entirely (cabal). As it is, the code handles .hls/dependency
being wiped out just fine, but would have trouble if just part of it were corrupted.
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 just One More Thing. At the moment users of HLS need to worry about:
dist-newstyle
~/.cache/ghcide
- and now
.hls
Plus, it's in the project directory, so everyone will have to add a new thing to their .gitignores
. It's not disastrous, but it is a real cost.
Does it need to be in the project root?
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 it needs to be in the project root to prevent vscode from spawning another HLS instance.
-- name and hash of the package the dependency module is | ||
-- found in. The name and hash are both parts of the UnitId. | ||
writeOutDir :: FilePath | ||
writeOutDir = projectRoot </> ".hls" </> "dependencies" </> show uid |
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 wonder if we should make the directory configurable.
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 making this directory configurable would be fine functionality to add to the project, but I don't think it should be in the same PR, as it's not strictly necessary for the functionality I'm trying to add here. I do think it's a good idea to get rid of the magic strings though.
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.
Yeah, in some ways making it configurable is partly a way to force the definition of the directory in one place! We could do that and then just not expose it to the user?
setFileModified (cmapWithPrio LogFileStore recorder) (VFSModified vfs) ide False file | ||
let foiStatus = case getSourceFileOrigin file of | ||
FromProject -> Modified{firstOpen=True} | ||
FromDependency -> ReadOnly |
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 should be impossible, right? A change notification for a read only file? Something has gone wrong here, we should probably at least log
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 found that editors (VSCode included) have various mechanisms for getting around readonly file permissions. So it is entirely possible for the user to accidentally or unwittingly edit one of these dependency files.
setFileModified (cmapWithPrio LogFileStore recorder) (VFSModified vfs) ide False file | ||
addFileOfInterest ide file foiStatus | ||
unless (foiStatus == ReadOnly) | ||
$ setFileModified (cmapWithPrio LogFileStore recorder) (VFSModified vfs) ide False file |
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 something go wrong if we do this even for ReadOnly things? comment!
@@ -38,7 +38,9 @@ moduleOutline | |||
moduleOutline ideState _ DocumentSymbolParams{ _textDocument = TextDocumentIdentifier uri } | |||
= liftIO $ case uriToFilePath uri of | |||
Just (toNormalizedFilePath' -> fp) -> do | |||
mb_decls <- fmap fst <$> runAction "Outline" ideState (useWithStale GetParsedModule fp) | |||
mb_decls <- case getSourceFileOrigin fp of | |||
FromDependency -> pure Nothing |
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.
again, why can't we just let the handler fail because the rule fails?
hls-plugin-api/src/Ide/Types.hs
Outdated
-- ^ File extension of the files the plugin is responsible for. | ||
-- The plugin is only allowed to handle files with these extensions. | ||
-- When writing handlers, etc. for this plugin it can be assumed that all handled files are of this type. | ||
-- The file extension must have a leading '.'. | ||
} | ||
|
||
-- A description of the types of files that the plugin |
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.
-- A description of the types of files that the plugin | |
-- | A description of the types of files that the plugin |
I realise I'm just repeating myself, but again I don't see why we can't let plugins just fail on dependency files if they need stuff that can't be provided.
hls-plugin-api/src/Ide/Types.hs
Outdated
-- project file. | ||
getSourceFileOrigin :: NormalizedFilePath -> SourceFileOrigin | ||
getSourceFileOrigin f = | ||
case [".hls", "dependencies"] `isInfixOf` (splitDirectories file) of |
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.
Another use of the magic strings!
User feedback: I've using this for about three days, going to third-party package is really really fantastic! I still found some packages like |
My big comments:
|
I took this design choice at the request of @wz1000. It was his idea to create a whitelist of Rules that we think are appropriate for dependency files. It was also his idea to create a notion of which file types plugins are defined for, defaulting to not supporting dependency files. @michaelpj I wonder what justification you would give for running code that we know will fail? I was under the impression that plugin failures were not something that were handled gracefully, but if they are I suppose it doesn't matter which way we go on this. It just seems wasteful to me and likely not very performant to run extra code. |
There are two main components of the functionality:
The The indexing process gets the packages and modules for dependencies from the Everything else is plumbing to make the two above functionalities work, code that disables functionality that won't work on dependency files (which may or may not be necessary as discussed above), and tests. @michaelpj does this answer your questions about logic flow? Do you think this should be documented somewhere other than this comment, and if so where? |
@July541 I think this is a consequence of how hls handles a plugin being enabled or disabled. This may be the first instance of many files in a project having multiple plugins disabled (which may not be the right approach anyway as @michaelpj pointed out above). I think maybe there are some changes that should be made that aren't directly related to this functionality. |
Great comment! Yes, please do write a Note! I would probably put it close to where the indexing is happening. Something like
👍
I think I asked this already, but how bad would it be to eagerly write out the source files and index them during the initial process? It would make startup slower, since we'd be doing work for files that we might not need, but it seems like it would simplify the logic quite a bit. Also, this process has the flavour of "do X, but only when it's requested". Would it make sense to handle this with a
Plugin failures and rule failures have to be handled somewhat gracefully, since failure is normal state. If the user has a Haskell file that has a parse error, then many things will fail! Rules that depend on parsing will fail, plugin handlers that depend on those rules will fail (some will work because they depend on stale information, but still). (I'm not too worried about the cost - the rule failures should cascade pretty quickly, I'd think) Maybe this will all be too much if we just can't process the file at all, but in some sense it seems like it should be fine if, say, the Perhaps this is harder than I think - I know we had similar issues with the cabal plugin, which is what led to us having the filetype associations for plugins. So I guess it's not a hard and fast rule. But the changes here seem more invasive, and I wonder if we could just go for the "let it fail" approach. |
cc84de6
to
3d098ba
Compare
7e00314
to
e9ea310
Compare
It is really great feature, do you still have time pushing it @nlander ? |
I would like to give it some more love soon, yes
…On Sat, Feb 10, 2024, 12:04 PM soulomoon ***@***.***> wrote:
It is really great feature, do you still have time pushing it @nlander
<https://github.com/nlander> ?
—
Reply to this email directly, view it on GitHub
<#3749 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABIFIGT5HNVXE7XDZIDDME3YS6SAXAVCNFSM6AAAAAA3IMXKRSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSMZXGA3DGOBZGI>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
For users using cabal HEAD, enables indexing of dependency HIE files so that the source can be written out on calls to gotoDefinition.
Opening this instead of #3704 because rebasing over the ghcide test refactor ended up being more trouble than it was worth.
There are a few things still missing, but I think this is ready for more eyes.
What I know is still missing - feedback on all of these items is welcome:
loadHieFile
inlookupMod
would fail. What should we do in this case? Should we send a message to the client? We should probably at least unindex the package.extra-compilation-artifacts
directory (where the HIE files should be found), but missingextra-compilation-artifacts
. This can happen if the project is build with the -fwrite-ide-info flag, but with an older version of cabal that does not produce the HIE files.