Skip to content

Support structured diagnostics #4311

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

Closed
Changes from 1 commit
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
d5b70e0
Change FileDiagnostic type synonym to a datatype
dylan-thinnes Jun 8, 2024
3c9ae07
Make `ideErrorWithSource` produce FileDiagnostic by adding filepath arg
dylan-thinnes Jun 8, 2024
ac78312
Supply structured error wherever we easily can - TODOs for hard parts
dylan-thinnes Jun 9, 2024
4b39d0f
Fix UnitTests for new FileDiagnostic struct
dylan-thinnes Jun 9, 2024
465ee2b
Remove explicit uses of FileDiagnostic, add codes to LSP diagnostics
dylan-thinnes Jun 9, 2024
4d2f3f0
Add field for expected error codes in ghcide tests
dylan-thinnes Jun 10, 2024
e4ca141
Expect GHC-83865 for "type error" test - basic test
dylan-thinnes Jun 10, 2024
2a2bc3d
Return structured warnings in TcModuleResult by copying from Driver
dylan-thinnes Jun 10, 2024
2cd33df
Store FileDiagnostic instead of LSP Diagnostic in Shake store
dylan-thinnes Jun 16, 2024
c4d5edd
Add expected error codes for diagnostics that have them
dylan-thinnes Jun 16, 2024
ae50843
Dispatch TODOs, amend remaining TODOs as future work
dylan-thinnes Jun 16, 2024
0cf77e5
Add scary comments all over copied code in Compat.Driver
dylan-thinnes Jun 16, 2024
4b452c9
Update all remaining diagnostics that could use an expected error code
dylan-thinnes Jun 16, 2024
25b02fa
Add _code to pretty printing for FileDiagnostic
dylan-thinnes Jun 16, 2024
a46f0a2
Use case instead of `maybe` for StructuredMessage match
dylan-thinnes Jun 16, 2024
25bfcb3
Use CPP to prevent setting _code before structured errors
dylan-thinnes Jun 16, 2024
003c15c
Swap modifier for lenses, document StructuredMessage type
dylan-thinnes Jun 16, 2024
3500ac3
Add link to Issue & MR to Compat.Driver
dylan-thinnes Jun 16, 2024
4fed987
Drop attachReason logic from withWarnings, technically incorrect
dylan-thinnes Jun 16, 2024
74b245d
Revert "Drop attachReason logic", needed by pragmas-plugin
dylan-thinnes Jun 16, 2024
326f314
Fix plugins where necessary for new diagnostic structure
dylan-thinnes Jun 16, 2024
52150c7
Fix build issues with other tests from `expectDiagnostics`
dylan-thinnes Jun 16, 2024
7ec0481
Improve comment on metadata fdStructuredMessage in FileDiagnostic
dylan-thinnes Jun 17, 2024
be37756
Add note to withWarnings explaining the current state of things
dylan-thinnes Jun 20, 2024
7bb82d0
Attach reasons into data field of LSP Diagnostic instead of code field
dylan-thinnes Jun 20, 2024
c248bb3
Merge remote-tracking branch 'upstream/master' into support-structure…
dylan-thinnes Jun 20, 2024
8d310fb
Fix up mistakes from merge, TODO fix merge issues for 9.3.0
dylan-thinnes Jun 20, 2024
414c845
Set CodeDescription from HaskellErrorIndex when available
dylan-thinnes Jun 24, 2024
fc22ac5
Remove debugging print, fix expectation for preprocessor tests
dylan-thinnes Jun 27, 2024
5bb39cd
Fix CPP for using Show instance on DiagnosticCode
dylan-thinnes Jun 27, 2024
8051130
Remove diagFromErrMsgs for GHC version < 9.6.1 using CPP
dylan-thinnes Jun 28, 2024
0e9d75e
CPP fix
dylan-thinnes Jun 28, 2024
863e42e
More stylish-haskell, more CPP fix
dylan-thinnes Jun 28, 2024
4c798e4
Fix all stylish-haskell errors triggering
dylan-thinnes Jun 28, 2024
b7761de
Fix more CPP
dylan-thinnes Jun 29, 2024
596a4cb
Only override the LSP diagnostic code when not already set
dylan-thinnes Jun 29, 2024
58cdc41
Fixes for stylish-haskell
dylan-thinnes Jun 29, 2024
503a861
Qualify s, t for FuzzySearch
dylan-thinnes Jun 29, 2024
3ad6bca
Ignore use of unsafePerformIO in FuzzySearch
dylan-thinnes Jun 29, 2024
c30267c
Properly split GHC.Types.Error import in Diagnostics for stylish-haskell
dylan-thinnes Jun 30, 2024
29133ba
Force type signature of annotation on FuzzySearch.dictionary
dylan-thinnes Jun 30, 2024
1a76f88
DRY up definition of closure_errs
dylan-thinnes Jul 2, 2024
f52e9c2
Merge remote-tracking branch 'upstream/master' into support-structure…
dylan-thinnes Aug 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add expected error codes for diagnostics that have them
  • Loading branch information
dylan-thinnes committed Jun 16, 2024
commit c4d5eddb4dc4a8cfdbeca6de354293e14c18da7b
54 changes: 27 additions & 27 deletions ghcide/test/exe/DiagnosticTests.hs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ tests = testGroup "diagnostics"
[ testWithDummyPluginEmpty "fix syntax error" $ do
let content = T.unlines [ "module Testing wher" ]
doc <- createDoc "Testing.hs" "haskell" content
expectDiagnostics [("Testing.hs", [(DiagnosticSeverity_Error, (0, 15), "parse error", Nothing)])]
expectDiagnostics [("Testing.hs", [(DiagnosticSeverity_Error, (0, 15), "parse error", Just "GHC-58481")])]
let change = TextDocumentContentChangeEvent $ InL TextDocumentContentChangePartial
{ _range = Range (Position 0 15) (Position 0 19)
, _rangeLength = Nothing
Expand All @@ -67,18 +67,18 @@ tests = testGroup "diagnostics"
, _text = "wher"
}
changeDoc doc [change]
expectDiagnostics [("Testing.hs", [(DiagnosticSeverity_Error, (0, 15), "parse error", Nothing)])]
expectDiagnostics [("Testing.hs", [(DiagnosticSeverity_Error, (0, 15), "parse error", Just "GHC-58481")])]
, testWithDummyPluginEmpty "update syntax error" $ do
let content = T.unlines [ "module Testing(missing) where" ]
doc <- createDoc "Testing.hs" "haskell" content
expectDiagnostics [("Testing.hs", [(DiagnosticSeverity_Error, (0, 15), "Not in scope: 'missing'", Nothing)])]
expectDiagnostics [("Testing.hs", [(DiagnosticSeverity_Error, (0, 15), "Not in scope: 'missing'", Just "GHC-76037")])]
let change = TextDocumentContentChangeEvent $ InL TextDocumentContentChangePartial
{ _range = Range (Position 0 15) (Position 0 16)
, _rangeLength = Nothing
, _text = "l"
}
changeDoc doc [change]
expectDiagnostics [("Testing.hs", [(DiagnosticSeverity_Error, (0, 15), "Not in scope: 'lissing'", Nothing)])]
expectDiagnostics [("Testing.hs", [(DiagnosticSeverity_Error, (0, 15), "Not in scope: 'lissing'", Just "GHC-76037")])]
, testWithDummyPluginEmpty "variable not in scope" $ do
let content = T.unlines
[ "module Testing where"
Expand All @@ -90,8 +90,8 @@ tests = testGroup "diagnostics"
_ <- createDoc "Testing.hs" "haskell" content
expectDiagnostics
[ ( "Testing.hs"
, [ (DiagnosticSeverity_Error, (2, 15), "Variable not in scope: ab", Nothing)
, (DiagnosticSeverity_Error, (4, 11), "Variable not in scope: cd", Nothing)
, [ (DiagnosticSeverity_Error, (2, 15), "Variable not in scope: ab", Just "GHC-88464")
, (DiagnosticSeverity_Error, (4, 11), "Variable not in scope: cd", Just "GHC-88464")
]
)
]
Expand All @@ -116,7 +116,7 @@ tests = testGroup "diagnostics"
_ <- createDoc "Testing.hs" "haskell" content
expectDiagnostics
[ ( "Testing.hs"
, [(DiagnosticSeverity_Error, (2, 8), "Found hole: _ :: Int -> String", Nothing)]
, [(DiagnosticSeverity_Error, (2, 8), "Found hole: _ :: Int -> String", Just "GHC-88464")]
)
]

Expand All @@ -131,17 +131,17 @@ tests = testGroup "diagnostics"
, "b :: Float"
, "b = True"]
bMessage = "Couldn't match expected type 'Float' with actual type 'Bool'"
expectedDs aMessage =
[ ("A.hs", [(DiagnosticSeverity_Error, (2,4), aMessage, Nothing)])
, ("B.hs", [(DiagnosticSeverity_Error, (3,4), bMessage, Nothing)])]
deferralTest title binding msg = testWithDummyPluginEmpty title $ do
expectedDs aMessage aCode =
[ ("A.hs", [(DiagnosticSeverity_Error, (2,4), aMessage, aCode)])
, ("B.hs", [(DiagnosticSeverity_Error, (3,4), bMessage, Just "GHC-83865")])]
deferralTest title binding msg code = testWithDummyPluginEmpty title $ do
_ <- createDoc "A.hs" "haskell" $ sourceA binding
_ <- createDoc "B.hs" "haskell" sourceB
expectDiagnostics $ expectedDs msg
expectDiagnostics $ expectedDs msg code
in
[ deferralTest "type error" "True" "Couldn't match expected type"
, deferralTest "typed hole" "_" "Found hole"
, deferralTest "out of scope var" "unbound" "Variable not in scope"
[ deferralTest "type error" "True" "Couldn't match expected type" (Just "GHC-83865")
, deferralTest "typed hole" "_" "Found hole" (Just "GHC-88464")
, deferralTest "out of scope var" "unbound" "Variable not in scope" (Just "GHC-88464")
]

, testWithDummyPluginEmpty "remove required module" $ do
Expand Down Expand Up @@ -243,7 +243,7 @@ tests = testGroup "diagnostics"
_ <- createDoc "ModuleA.hs" "haskell" contentA
_ <- createDoc "ModuleB.hs" "haskell" contentB
_ <- createDoc "ModuleB.hs-boot" "haskell" contentBboot
expectDiagnostics [("ModuleB.hs", [(DiagnosticSeverity_Warning, (3,0), "Top-level binding", Nothing)])]
expectDiagnostics [("ModuleB.hs", [(DiagnosticSeverity_Warning, (3,0), "Top-level binding", Just "GHC-38417")])]
, testWithDummyPlugin "bidirectional module dependency with hs-boot"
(mkIdeTestFs [directCradle ["ModuleA", "ModuleB"]])
$ do
Expand All @@ -268,7 +268,7 @@ tests = testGroup "diagnostics"
_ <- createDoc "ModuleA.hs-boot" "haskell" contentAboot
_ <- createDoc "ModuleB.hs" "haskell" contentB
_ <- createDoc "ModuleB.hs-boot" "haskell" contentBboot
expectDiagnostics [("ModuleB.hs", [(DiagnosticSeverity_Warning, (3,0), "Top-level binding", Nothing)])]
expectDiagnostics [("ModuleB.hs", [(DiagnosticSeverity_Warning, (3,0), "Top-level binding", Just "GHC-38417")])]
, testWithDummyPluginEmpty "correct reference used with hs-boot" $ do
let contentB = T.unlines
[ "module ModuleB where"
Expand All @@ -294,7 +294,7 @@ tests = testGroup "diagnostics"
_ <- createDoc "ModuleA.hs" "haskell" contentA
_ <- createDoc "ModuleA.hs-boot" "haskell" contentAboot
_ <- createDoc "ModuleC.hs" "haskell" contentC
expectDiagnostics [("ModuleC.hs", [(DiagnosticSeverity_Warning, (3,0), "Top-level binding", Nothing)])]
expectDiagnostics [("ModuleC.hs", [(DiagnosticSeverity_Warning, (3,0), "Top-level binding", Just "GHC-38417")])]
, testWithDummyPluginEmpty "redundant import" $ do
let contentA = T.unlines ["module ModuleA where"]
let contentB = T.unlines
Expand All @@ -320,7 +320,7 @@ tests = testGroup "diagnostics"
]
_ <- createDoc "ModuleA.hs" "haskell" contentA
_ <- createDoc "ModuleB.hs" "haskell" contentB
expectDiagnostics [("ModuleB.hs", [(DiagnosticSeverity_Warning, (3,0), "Top-level binding", Nothing)])]
expectDiagnostics [("ModuleB.hs", [(DiagnosticSeverity_Warning, (3,0), "Top-level binding", Just "GHC-38417")])]
, testWithDummyPluginEmpty "package imports" $ do
let thisDataListContent = T.unlines
[ "module Data.List where"
Expand Down Expand Up @@ -348,14 +348,14 @@ tests = testGroup "diagnostics"
else if ghcVersion >= GHC94 then
"Variable not in scope: map" -- See https://gitlab.haskell.org/ghc/ghc/-/issues/22130
else
"Not in scope: \8216ThisList.map\8217", Nothing)
"Not in scope: \8216ThisList.map\8217", Just "GHC-88464")
,(DiagnosticSeverity_Error, (7, 9),
if ghcVersion >= GHC96 then
"Variable not in scope: BaseList.x"
else if ghcVersion >= GHC94 then
"Variable not in scope: x" -- See https://gitlab.haskell.org/ghc/ghc/-/issues/22130
else
"Not in scope: \8216BaseList.x\8217", Nothing)
"Not in scope: \8216BaseList.x\8217", Just "GHC-88464")
]
)
]
Expand All @@ -373,7 +373,7 @@ tests = testGroup "diagnostics"
-- where appropriate. The warning should use an unqualified name 'Ord', not
-- something like 'GHC.Classes.Ord'. The choice of redundant-constraints to
-- test this is fairly arbitrary.
, [(DiagnosticSeverity_Warning, (2, if ghcVersion >= GHC94 then 7 else 0), "Redundant constraint: Ord a", Nothing)
, [(DiagnosticSeverity_Warning, (2, if ghcVersion >= GHC94 then 7 else 0), "Redundant constraint: Ord a", Just "GHC-30606")
]
)
]
Expand Down Expand Up @@ -469,13 +469,13 @@ tests = testGroup "diagnostics"
bdoc <- createDoc bPath "haskell" bSource
_pdoc <- createDoc pPath "haskell" pSource
expectDiagnostics
[("P.hs", [(DiagnosticSeverity_Warning,(4,0), "Top-level binding", Nothing)])] -- So that we know P has been loaded
[("P.hs", [(DiagnosticSeverity_Warning,(4,0), "Top-level binding", Just "GHC-38417")])] -- So that we know P has been loaded

-- Change y from Int to B which introduces a type error in A (imported from P)
changeDoc bdoc [TextDocumentContentChangeEvent . InR . TextDocumentContentChangeWholeDocument $
T.unlines ["module B where", "y :: Bool", "y = undefined"]]
expectDiagnostics
[("A.hs", [(DiagnosticSeverity_Error, (5, 4), "Couldn't match expected type 'Int' with actual type 'Bool'", Nothing)])
[("A.hs", [(DiagnosticSeverity_Error, (5, 4), "Couldn't match expected type 'Int' with actual type 'Bool'", Just "GHC-83865")])
]

-- Open A and edit to fix the type error
Expand All @@ -485,8 +485,8 @@ tests = testGroup "diagnostics"

expectDiagnostics
[ ( "P.hs",
[ (DiagnosticSeverity_Error, (4, 6), "Couldn't match expected type 'Int' with actual type 'Bool'", Nothing),
(DiagnosticSeverity_Warning, (4, 0), "Top-level binding", Nothing)
[ (DiagnosticSeverity_Error, (4, 6), "Couldn't match expected type 'Int' with actual type 'Bool'", Just "GHC-83865"),
(DiagnosticSeverity_Warning, (4, 0), "Top-level binding", Just "GHC-38417")
]
),
("A.hs", [])
Expand Down Expand Up @@ -564,7 +564,7 @@ cancellationTemplate (edit, undoEdit) mbKey = testCase (maybe "-" fst mbKey) $ r
]

-- for the example above we expect one warning
let missingSigDiags = [(DiagnosticSeverity_Warning, (3, 0), "Top-level binding", Nothing) ]
let missingSigDiags = [(DiagnosticSeverity_Warning, (3, 0), "Top-level binding", Just "GHC-38417") ]
typeCheck doc >> expectCurrentDiagnostics doc missingSigDiags

-- Now we edit the document and wait for the given key (if any)
Expand Down