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

Support structured diagnostics 2 #4433

Open
wants to merge 69 commits into
base: master
Choose a base branch
from

Conversation

noughtmare
Copy link
Contributor

@noughtmare noughtmare commented Oct 17, 2024

This is my attempt at finishing the work of @dylan-thinnes on !4311.

Addresses #2014

Should hopefully enable #3246

These are two things Dylan listed as work for future PRs:

  • Replacing regexes with structured diagnostic checks
  • Improve typing so that it can be known that an error has a structured diagnostic, instead of defaulting to Maybe

Some future work discovered in reviews of this PR:

  • requireDiagnostic could take a more structured error code query type as argument. See Support structured diagnostics 2 #4433 (comment)
  • The HTTP work should be un-reverted in a future PR: 1bc221c
  • Check that tests using requireDiagnostics and related functions use explicit error codes if possible

@noughtmare
Copy link
Contributor Author

All failures in the jobs of e651d41 seem to be spurious (except for the stylish-haskell formatting failure).

@noughtmare
Copy link
Contributor Author

I think the remaining failures are not caused by this PR. Are these kinds of spurious failures common in HLS?

Also, I would really like to get this merged before the next release, because I want to develop a VS Code extension which uses these diagnostic numbers.

@fendor
Copy link
Collaborator

fendor commented Oct 18, 2024

Are these kinds of spurious failures common in HLS?

Yes, they unfortunately are

@fendor
Copy link
Collaborator

fendor commented Oct 18, 2024

Some errors in ghc 9.4 seem to be genuine, though. Many tests are seemingly time outing for some reason.

@noughtmare
Copy link
Contributor Author

You're right. Can anyone give me some tips on how to profile HLS to see where these timeouts are coming from?

@fendor
Copy link
Collaborator

fendor commented Oct 18, 2024

@noughtmare Profiling is likely not necessary, I think the tests are waiting for an LSP message that never arrives, and then just wait for 60s and time out.

Use HLS_TEST_LOG_STDERR=1 cabal test ... and TASTY_PATTERN to run a specific test with all HLS logging enabled.
Printf debugging also works quite well to figure out where the tests gets stuck.
To get the raw LSP messages, you can use LSP_TEST_LOG_MESSAGES=1 or LSP_TEST_LOG_STDERR=1 (they do the same thign)

@noughtmare
Copy link
Contributor Author

noughtmare commented Oct 18, 2024

Ah, I was thinking there was some inefficiency somewhere that only GHC 9.6 and later could properly optimize. However, I think you're suggesting an alternative explanation: that one of the conditional CPP blocks contains an actual correctness issue. Perhaps I could just visually inspect those first; I don't think that would be that much work.

Edit: no obvious loops or anything, so perhaps some tracing would indeed be better.

@noughtmare
Copy link
Contributor Author

noughtmare commented Oct 22, 2024

I've decided to make the tests ignore all error codes on GHC 9.4. I think some errors already have codes in 9.4, so we could do a bit more, but I don't think it is worth the effort.

@noughtmare
Copy link
Contributor Author

noughtmare commented Oct 23, 2024

The remaining MacOS failure seems like a compiler bug. The linker is throwing an error.

Edit: https://gitlab.haskell.org/ghc/ghc/-/issues/24648

Adding the compiler flag -ld_classic might be a workaround.

@noughtmare
Copy link
Contributor Author

@fendor do you think we could try setting the -ld_classic flag? If so, where should I put it?

@noughtmare
Copy link
Contributor Author

noughtmare commented Oct 23, 2024

Oh, I see we already have that exact workaround in some places. I'll just copy that to the hlint plugin.

@noughtmare
Copy link
Contributor Author

noughtmare commented Oct 23, 2024

Yay, it has finally passed CI! Should I squash the commits? I'm not sure what to write in the message as I don't really know the details of what exactly Dylan did.

@noughtmare noughtmare requested a review from michaelpj as a code owner October 23, 2024 13:36
@noughtmare noughtmare force-pushed the support-structured-diagnostics branch from 7773572 to 469d8a7 Compare October 23, 2024 13:37
@noughtmare
Copy link
Contributor Author

Thank you for the reviews! I hope I have addressed all feedback appropriately. Is there anything more I can do to speed up the process of merging this?

@fendor
Copy link
Collaborator

fendor commented Nov 2, 2024

Probably not, except for regularly pinging on this thread to make sure we get enough reviews, soon :) We need two approvals, considering the importance of this change, we shouldn't rush merging it without proper review time.

However, I hope we can merge it within the next two weeks (hopefully a pessimistic timeframe, but I don't really want to give any time estimate at all :D ).

@fendor fendor added the status: needs review This PR is ready for review label Nov 2, 2024
@fendor fendor requested review from soulomoon and fendor November 2, 2024 15:30
Copy link
Collaborator

@soulomoon soulomoon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a question, other places look good to me.

plugins/hls-refactor-plugin/test/Main.hs Outdated Show resolved Hide resolved
@soulomoon soulomoon self-requested a review November 4, 2024 16:51
@noughtmare
Copy link
Contributor Author

regularly pinging

ping

@fendor
Copy link
Collaborator

fendor commented Nov 19, 2024

In the last HLS meeting, we discussed this PR and what we want from it, for transparency, these are the notes https://docs.google.com/document/d/1zqRhA3uoiYgA_Q8eDpIEG0OiFcofGqkVP7N4ODDmikM/edit?tab=t.0

In short, I will review soon and try to make use of the structured diagnostics in 1 or 2 of the plugins, to demonstrate how we can use them in the future and to make sure this PR takes the right directions.
Are you fine with me pushing to this branch, or should I open PRs against your branch?

@noughtmare
Copy link
Contributor Author

I'm fine with pushing directly to my branch if that is possible. Do I need to give you special permissions?

@fendor
Copy link
Collaborator

fendor commented Nov 19, 2024

I don't know, I will just try to push at some point and ping you if I have any trouble :)

Implement 'rangesOverlap' function which checks whether two 'Range's
overlap in any way.
Implement two new plugin utility functions which allow to conveniently
get all currently displayed diagnostics for a given 'Range'.
@fendor fendor force-pushed the support-structured-diagnostics branch 2 times, most recently from 48e1288 to af550e3 Compare November 30, 2024 15:15
Add compatibility module for GHC's structured error messages.
Introduce 'Prism's and 'Lens's to easily access nested structures.
Expand documentation for 'StructuredMessage'
@fendor fendor force-pushed the support-structured-diagnostics branch from af550e3 to f4d5c24 Compare November 30, 2024 15:17
Copy link
Collaborator

@fendor fendor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It took me long enough, but I am happy with the PR now.

I still have to address my own comments, and likely I have to revert any changes to the plugins and split these commits off into a separate PR.

Comment on lines +1162 to +1166
#if MIN_VERSION_ghc(9,5,0)
throwE $ diagFromErrMsgs sourceParser dflags errors
#else
throwE $ diagFromSDocErrMsgs sourceParser dflags errors
#endif
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to myself, check whether we can hide this CPP in a function such as diagFromGhcErrorMessage with appropriate #ifs and typedefs to avoid the CPP statements here.

@@ -157,6 +158,7 @@ data TcModuleResult = TcModuleResult
-- ^ Which modules did we need at runtime while compiling this file?
-- Used for recompilation checking in the presence of TH
-- Stores the hash of their core file
, tmrWarnings :: WarningMessages
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self, add docs for this.

Comment on lines +121 to +127
#if MIN_VERSION_ghc(9,5,0)
type ErrMsg = MsgEnvelope GhcMessage
type WarnMsg = MsgEnvelope GhcMessage
#else
type ErrMsg = MsgEnvelope DecoratedSDoc
type WarnMsg = MsgEnvelope DecoratedSDoc
#endif
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self, this feels like the wrong direction, we should have type defs for backwards compatibility, i.e.

#if !MIN_VERSION_ghc(9,5,0)
type GhcMessage = DecoratedSDoc
```endif

which allows us to write code conforming to the latest GHC API.

I think it is more confusing and less maintainable in the long run, if we add type defs to maintain the previous API.

Comment on lines +16 to +17
{-
NOTE on withWarnings and its dangers
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self, improper GHC Note syntax

@fendor
Copy link
Collaborator

fendor commented Dec 1, 2024

@noughtmare Is there anythign else you need or want from this PR?

@noughtmare
Copy link
Contributor Author

I personally just wanted access to the diagnostic codes. So I'm more than satisfied!

Copy link
Collaborator

@soulomoon soulomoon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, Just two questions

@@ -80,23 +86,25 @@ addMethodPlaceholders _ state _ param@AddMinimalMethodsParams{..} = do
-- This implementation is ad-hoc in a sense that the diagnostic detection mechanism is
-- sensitive to the format of diagnostic messages from GHC.
codeAction :: Recorder (WithPriority Log) -> PluginMethodHandler IdeState Method_TextDocumentCodeAction
codeAction recorder state plId (CodeActionParams _ _ docId _ context) = do
codeAction recorder state plId (CodeActionParams _ _ docId caRange _) = do
Copy link
Collaborator

@soulomoon soulomoon Dec 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, now we are getting the diags from diags store in ShakeExtra instead of CodeActionContext.
Two questions:

  1. Does it mean diags in ShakeExtra contains more information than the one in the CodeActionContext now ?
  2. Do these two places' diags always in sync (e.g., is there additional filters for diags in the CodeActionContext, but those filters not in diags store in ShakeExtra)?

Copy link
Collaborator

@fendor fendor Dec 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, that's exactly what we are doing :)

Re 1., I think ShakeExtra also contains Diagnostics which are not displayed to the user, see the docs for ShowDiagnostic:

-- | Defines whether a particular diagnostic should be reported
--   back to the user.
--
--   One important use case is "missing signature" code lenses,
--   for which we need to enable the corresponding warning during
--   type checking. However, we do not want to show the warning
--   unless the programmer asks for it (#261).
data ShowDiagnostic
    = ShowDiag  -- ^ Report back to the user
    | HideDiag  -- ^ Hide from user
    deriving (Eq, Ord, Show)

This means, we may have more diagnostics available.

Re 2., I confidently, but without evidence, claim that the diagnostics sent by the client and the diagnostics we store in StoreExtras may be out of sync, but it has no noticeable negative effect for the user experience.

However, why are we doing this? Primarily due to the docs of CodeActionContext:

  /**
    * An array of diagnostics known on the client side overlapping the range
    * provided to the `textDocument/codeAction` request. They are provided so
    * that the server knows which errors are currently presented to the user
    * for the given range. There is no guarantee that these accurately reflect
    * the error state of the resource. The primary parameter
    * to compute code actions is the provided range.
    */
   diagnostics: Diagnostic[];

Which tells us that we cannot rely on the diagnostics provided by the CodeActionContext.
I will add this crucial bit of information to the documentation of activeDiagnostics... function.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, adding it to the docs helps for the future reviewers.:)

<+> pretty (show (getOccString cls) <> ":") -- 'show' is used here to add quotes around the class name
<+> pretty methods
<+> pretty (showSDocUnsafe $ ppr methods)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we safe with showSDocUnsafe ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's fine for logging, unsafe doesn't mean it might crash, but rather we use default DynFlags which may be missing some information, such as import paths, packages in scope, etc... So, the displayed names may be inaccurate. However, I can double-check what we do in other locations

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should get the more exact DynFlags from rule like GetModSummary, but, I agree, for logging, it should be fine as long as it won't crash.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance Issues about memory consumption, responsiveness, etc. status: needs review This PR is ready for review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants