Simon Hengel pushed to branch wip/sol/add-rendered-to-json-diagnostics at Glasgow Haskell Compiler / GHC
Commits:
-
ddd19d42
by Simon Hengel at 2025-07-08T05:30:17+07:00
-
33746bc6
by Simon Hengel at 2025-07-08T05:30:31+07:00
9 changed files:
- compiler/GHC/Driver/Errors.hs
- compiler/GHC/Types/Error.hs
- compiler/GHC/Utils/Logger.hs
- compiler/GHC/Utils/Ppr.hs
- docs/users_guide/9.14.1-notes.rst
- + docs/users_guide/diagnostics-as-json-schema-1_2.json
- docs/users_guide/using.rst
- testsuite/tests/driver/json.stderr
- testsuite/tests/driver/json_warn.stderr
Changes:
... | ... | @@ -7,27 +7,63 @@ module GHC.Driver.Errors ( |
7 | 7 | |
8 | 8 | import GHC.Driver.Errors.Types
|
9 | 9 | import GHC.Prelude
|
10 | +import GHC.Types.SrcLoc (SrcSpan)
|
|
10 | 11 | import GHC.Types.SourceError
|
11 | 12 | import GHC.Types.Error
|
13 | +import GHC.Utils.Json
|
|
12 | 14 | import GHC.Utils.Error
|
13 | -import GHC.Utils.Outputable (hang, ppr, ($$), text, mkErrStyle, sdocStyle, updSDocContext )
|
|
15 | +import GHC.Utils.Outputable
|
|
14 | 16 | import GHC.Utils.Logger
|
15 | 17 | |
16 | 18 | printMessages :: forall a. (Diagnostic a) => Logger -> DiagnosticOpts a -> DiagOpts -> Messages a -> IO ()
|
17 | -printMessages logger msg_opts opts msgs
|
|
18 | - = sequence_ [ let style = mkErrStyle name_ppr_ctx
|
|
19 | - ctx = (diag_ppr_ctx opts) { sdocStyle = style }
|
|
20 | - in (if log_diags_as_json
|
|
21 | - then logJsonMsg logger (MCDiagnostic sev reason (diagnosticCode dia)) msg
|
|
22 | - else logMsg logger (MCDiagnostic sev reason (diagnosticCode dia)) s $
|
|
23 | - updSDocContext (\_ -> ctx) (messageWithHints dia))
|
|
24 | - | msg@MsgEnvelope { errMsgSpan = s,
|
|
25 | - errMsgDiagnostic = dia,
|
|
26 | - errMsgSeverity = sev,
|
|
27 | - errMsgReason = reason,
|
|
28 | - errMsgContext = name_ppr_ctx }
|
|
29 | - <- sortMsgBag (Just opts) (getMessages msgs) ]
|
|
19 | +printMessages logger msg_opts opts = mapM_ printMessage . sortMessages
|
|
30 | 20 | where
|
21 | + sortMessages :: Messages a -> [MsgEnvelope a]
|
|
22 | + sortMessages = sortMsgBag (Just opts) . getMessages
|
|
23 | + |
|
24 | + printMessage :: MsgEnvelope a -> IO ()
|
|
25 | + printMessage message
|
|
26 | + | log_diags_as_json = do
|
|
27 | + docWithHeader <- addCaret logflags messageClass location (addHeader doc)
|
|
28 | + let
|
|
29 | + rendered :: String
|
|
30 | + rendered = renderWithContext (log_default_user_context logflags) docWithHeader
|
|
31 | + |
|
32 | + jsonMessage :: JsonDoc
|
|
33 | + jsonMessage = case json message of
|
|
34 | + JSObject xs -> JSObject (("rendered", JSString rendered) : xs)
|
|
35 | + xs -> xs
|
|
36 | + logJsonMsg logger messageClass jsonMessage
|
|
37 | + |
|
38 | + | otherwise = logMsg logger messageClass location doc
|
|
39 | + where
|
|
40 | + logflags :: LogFlags
|
|
41 | + logflags = logFlags logger
|
|
42 | + |
|
43 | + addHeader :: SDoc -> SDoc
|
|
44 | + addHeader = mkLocMessageWarningGroups (log_show_warn_groups logflags) messageClass location
|
|
45 | + |
|
46 | + doc :: SDoc
|
|
47 | + doc = updSDocContext (\_ -> ctx) (messageWithHints diagnostic)
|
|
48 | + |
|
49 | + messageClass :: MessageClass
|
|
50 | + messageClass = MCDiagnostic severity (errMsgReason message) (diagnosticCode diagnostic)
|
|
51 | + |
|
52 | + style :: PprStyle
|
|
53 | + style = mkErrStyle (errMsgContext message)
|
|
54 | + |
|
55 | + location :: SrcSpan
|
|
56 | + location = errMsgSpan message
|
|
57 | + |
|
58 | + ctx :: SDocContext
|
|
59 | + ctx = (diag_ppr_ctx opts) { sdocStyle = style }
|
|
60 | + |
|
61 | + diagnostic :: a
|
|
62 | + diagnostic = errMsgDiagnostic message
|
|
63 | + |
|
64 | + severity :: Severity
|
|
65 | + severity = errMsgSeverity message
|
|
66 | + |
|
31 | 67 | messageWithHints :: a -> SDoc
|
32 | 68 | messageWithHints e =
|
33 | 69 | let main_msg = formatBulleted $ diagnosticMessage msg_opts e
|
... | ... | @@ -36,6 +72,8 @@ printMessages logger msg_opts opts msgs |
36 | 72 | [h] -> main_msg $$ hang (text "Suggested fix:") 2 (ppr h)
|
37 | 73 | hs -> main_msg $$ hang (text "Suggested fixes:") 2
|
38 | 74 | (formatBulleted $ mkDecorated . map ppr $ hs)
|
75 | + |
|
76 | + log_diags_as_json :: Bool
|
|
39 | 77 | log_diags_as_json = log_diagnostics_as_json (logFlags logger)
|
40 | 78 | |
41 | 79 | -- | Given a bag of diagnostics, turn them into an exception if
|
... | ... | @@ -573,7 +573,7 @@ instance ToJson DiagnosticCode where |
573 | 573 | {- Note [Diagnostic Message JSON Schema]
|
574 | 574 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
575 | 575 | The below instance of ToJson must conform to the JSON schema
|
576 | -specified in docs/users_guide/diagnostics-as-json-schema-1_1.json.
|
|
576 | +specified in docs/users_guide/diagnostics-as-json-schema-1_2.json.
|
|
577 | 577 | When the schema is altered, please bump the version.
|
578 | 578 | If the content is altered in a backwards compatible way,
|
579 | 579 | update the minor version (e.g. 1.3 ~> 1.4).
|
... | ... | @@ -21,6 +21,8 @@ module GHC.Utils.Logger |
21 | 21 | , HasLogger (..)
|
22 | 22 | , ContainsLogger (..)
|
23 | 23 | |
24 | + , addCaret
|
|
25 | + |
|
24 | 26 | -- * Logger setup
|
25 | 27 | , initLogger
|
26 | 28 | , LogAction
|
... | ... | @@ -421,24 +423,65 @@ defaultLogActionWithHandles out err logflags msg_class srcSpan msg |
421 | 423 | MCDiagnostic SevIgnore _ _ -> pure () -- suppress the message
|
422 | 424 | MCDiagnostic _sev _rea _code -> printDiagnostics
|
423 | 425 | where
|
424 | - printOut = defaultLogActionHPrintDoc logflags False out
|
|
425 | - printErrs = defaultLogActionHPrintDoc logflags False err
|
|
426 | + printOut :: SDoc -> IO ()
|
|
427 | + printOut = defaultLogActionHPrintDoc logflags False out
|
|
428 | + |
|
429 | + printErrs :: SDoc -> IO ()
|
|
430 | + printErrs = defaultLogActionHPrintDoc logflags False err
|
|
431 | + |
|
432 | + putStrSDoc :: SDoc -> IO ()
|
|
426 | 433 | putStrSDoc = defaultLogActionHPutStrDoc logflags False out
|
434 | + |
|
427 | 435 | -- Pretty print the warning flag, if any (#10752)
|
436 | + message :: SDoc
|
|
428 | 437 | message = mkLocMessageWarningGroups (log_show_warn_groups logflags) msg_class srcSpan msg
|
429 | 438 | |
430 | - printDiagnostics = do
|
|
431 | - caretDiagnostic <-
|
|
432 | - if log_show_caret logflags
|
|
433 | - then getCaretDiagnostic msg_class srcSpan
|
|
434 | - else pure empty
|
|
435 | - printErrs $ getPprStyle $ \style ->
|
|
436 | - withPprStyle (setStyleColoured True style)
|
|
437 | - (message $+$ caretDiagnostic $+$ blankLine)
|
|
438 | - -- careful (#2302): printErrs prints in UTF-8,
|
|
439 | - -- whereas converting to string first and using
|
|
440 | - -- hPutStr would just emit the low 8 bits of
|
|
441 | - -- each unicode char.
|
|
439 | + printDiagnostics :: IO ()
|
|
440 | + printDiagnostics = addCaret logflags msg_class srcSpan message >>= printErrs
|
|
441 | + |
|
442 | +-- This function is used by `defaultLogActionWithHandles` for non-JSON output,
|
|
443 | +-- and also by `GHC.Driver.Errors.printMessages` to produce the `rendered`
|
|
444 | +-- message on `-fdiagnostics-as-json`.
|
|
445 | +--
|
|
446 | +-- We would want to eventually consolidate this. However, this is currently
|
|
447 | +-- not feasible for the following reasons:
|
|
448 | +--
|
|
449 | +-- 1. Some parts of the compiler sidestep `printMessages`, for that reason we
|
|
450 | +-- can not decorate (`addCaret` + `defaultLogActionHPrintDoc`) the
|
|
451 | +-- message in `printMessages`.
|
|
452 | +--
|
|
453 | +-- 2. GHC uses two different code paths for JSON and non-JSON diagnostics. For
|
|
454 | +-- that reason we can decorate the message in `defaultLogActionWithHandles`.
|
|
455 | +--
|
|
456 | +-- See also Note [JSON Error Messages]:
|
|
457 | +--
|
|
458 | +-- `jsonLogAction` should be removed along with -ddump-json
|
|
459 | +--
|
|
460 | +-- Also note that (1) is the reason why some parts of the compiler produce
|
|
461 | +-- diagnostics that don't respect `-fdiagnostics-as-json`.
|
|
462 | +--
|
|
463 | +-- The plan as I see it is as follows:
|
|
464 | +--
|
|
465 | +-- 1. Refactor all places in the compiler that report diagnostics to go
|
|
466 | +-- through `GHC.Driver.Errors.printMessages`.
|
|
467 | +--
|
|
468 | +-- (It's easy to find all those places by looking for who creates
|
|
469 | +-- MCDiagnostic, either directly or via `mkMCDiagnostic` or
|
|
470 | +-- `errorDiagnostic`.)
|
|
471 | +--
|
|
472 | +-- 2. Get rid of `-ddump-json`, `jsonLogAction` and consolidate message
|
|
473 | +-- decoration at one place (either `printMessages` or
|
|
474 | +-- `defaultLogActionWithHandles`)
|
|
475 | +--
|
|
476 | +addCaret :: LogFlags -> MessageClass -> SrcSpan -> SDoc -> IO SDoc
|
|
477 | +addCaret logflags msg_class srcSpan message = do
|
|
478 | + caretDiagnostic <-
|
|
479 | + if log_show_caret logflags
|
|
480 | + then getCaretDiagnostic msg_class srcSpan
|
|
481 | + else pure empty
|
|
482 | + return $ getPprStyle $ \style ->
|
|
483 | + withPprStyle (setStyleColoured True style)
|
|
484 | + (message $+$ caretDiagnostic $+$ blankLine)
|
|
442 | 485 | |
443 | 486 | -- | Like 'defaultLogActionHPutStrDoc' but appends an extra newline.
|
444 | 487 | defaultLogActionHPrintDoc :: LogFlags -> Bool -> Handle -> SDoc -> IO ()
|
... | ... | @@ -474,6 +517,8 @@ defaultLogActionHPutStrDoc logflags asciiSpace h d |
474 | 517 | -- -ddump-json is being deprecated, `jsonLogAction` has been added in, but
|
475 | 518 | -- it should be removed along with -ddump-json. Similarly, the guard in
|
476 | 519 | -- `defaultLogAction` should be removed. This cleanup is tracked in #24113.
|
520 | +--
|
|
521 | +--
|
|
477 | 522 | |
478 | 523 | -- | Default action for 'dumpAction' hook
|
479 | 524 | defaultDumpAction :: DumpCache -> LogAction -> DumpAction
|
... | ... | @@ -603,8 +648,8 @@ defaultTraceAction logflags title doc x = |
603 | 648 | logMsg :: Logger -> MessageClass -> SrcSpan -> SDoc -> IO ()
|
604 | 649 | logMsg logger mc loc msg = putLogMsg logger (logFlags logger) mc loc msg
|
605 | 650 | |
606 | -logJsonMsg :: ToJson a => Logger -> MessageClass -> a -> IO ()
|
|
607 | -logJsonMsg logger mc d = putJsonLogMsg logger (logFlags logger) mc (json d)
|
|
651 | +logJsonMsg :: Logger -> MessageClass -> JsonDoc -> IO ()
|
|
652 | +logJsonMsg logger mc = putJsonLogMsg logger (logFlags logger) mc
|
|
608 | 653 | |
609 | 654 | -- | Dump something
|
610 | 655 | logDumpFile :: Logger -> PprStyle -> DumpFlag -> String -> DumpFormat -> SDoc -> IO ()
|
... | ... | @@ -1114,6 +1114,7 @@ printDoc_ mode pprCols hdl doc |
1114 | 1114 | = do { fullRender mode pprCols 1.5 put done doc ;
|
1115 | 1115 | hFlush hdl }
|
1116 | 1116 | where
|
1117 | + put :: TextDetails -> IO a -> IO a
|
|
1117 | 1118 | put (Chr c) next = hPutChar hdl c >> next
|
1118 | 1119 | put (Str s) next = hPutStr hdl s >> next
|
1119 | 1120 | put (PStr s) next = hPutStr hdl (unpackFS s) >> next
|
... | ... | @@ -1126,6 +1127,8 @@ printDoc_ mode pprCols hdl doc |
1126 | 1127 | = putSpaces n >> next
|
1127 | 1128 | | otherwise
|
1128 | 1129 | = hPutStr hdl (replicate n c) >> next
|
1130 | + |
|
1131 | + putSpaces :: Int -> IO ()
|
|
1129 | 1132 | putSpaces n
|
1130 | 1133 | -- If we use ascii spaces we are allowed to use hPutBuf
|
1131 | 1134 | -- See Note [putSpaces optimizations]
|
... | ... | @@ -1138,11 +1141,12 @@ printDoc_ mode pprCols hdl doc |
1138 | 1141 | |
1139 | 1142 | | otherwise = hPutStr hdl (replicate n ' ')
|
1140 | 1143 | |
1144 | + done :: IO ()
|
|
1141 | 1145 | done = return () -- hPutChar hdl '\n'
|
1146 | + |
|
1142 | 1147 | -- 100 spaces, so we avoid the allocation of replicate n ' '
|
1143 | 1148 | spaces' = " "#
|
1144 | 1149 | |
1145 | - |
|
1146 | 1150 | -- some versions of hPutBuf will barf if the length is zero
|
1147 | 1151 | hPutPtrString :: Handle -> PtrString -> IO ()
|
1148 | 1152 | hPutPtrString _handle (PtrString _ 0) = return ()
|
... | ... | @@ -143,6 +143,11 @@ Compiler |
143 | 143 | were accessed using the generated record selector functions, marking the fields
|
144 | 144 | as covered in coverage reports (:ghc-ticket:`17834`).
|
145 | 145 | |
146 | +- JSON diagnostics produced with (:ghc-flag:`-fdiagnostics-as-json`) now
|
|
147 | + include the `rendered` diagnostics message, in the exact same format as what
|
|
148 | + GHC would have produced without -fdiagnostics-as-json (including ANSI escape
|
|
149 | + sequences).
|
|
150 | + |
|
146 | 151 | GHCi
|
147 | 152 | ~~~~
|
148 | 153 |
1 | +{
|
|
2 | + "$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3 | + "title": "JSON Diagnostic Schema",
|
|
4 | + "description": "A Schema for specifying GHC diagnostics output as JSON",
|
|
5 | + "type": "object",
|
|
6 | + "properties": {
|
|
7 | + "version": {
|
|
8 | + "description": "The current JSON schema version this object conforms to",
|
|
9 | + "type": "string"
|
|
10 | + },
|
|
11 | + "ghcVersion": {
|
|
12 | + "description": "The GHC version",
|
|
13 | + "type": "string"
|
|
14 | + },
|
|
15 | + "span": {
|
|
16 | + "oneOf": [
|
|
17 | + { "$ref": "#/$defs/span" },
|
|
18 | + { "type": "null" }
|
|
19 | + ]
|
|
20 | + },
|
|
21 | + "severity": {
|
|
22 | + "description": "The diagnostic severity",
|
|
23 | + "type": "string",
|
|
24 | + "enum": [
|
|
25 | + "Warning",
|
|
26 | + "Error"
|
|
27 | + ]
|
|
28 | + },
|
|
29 | + "code": {
|
|
30 | + "description": "The diagnostic code (if it exists)",
|
|
31 | + "type": [
|
|
32 | + "integer",
|
|
33 | + "null"
|
|
34 | + ]
|
|
35 | + },
|
|
36 | + "rendered": {
|
|
37 | + "description": "The rendered diagnostics message, in the exact same format as what GHC would have produced without -fdiagnostics-as-json (including ANSI escape sequences)",
|
|
38 | + "type": "string"
|
|
39 | + },
|
|
40 | + "message": {
|
|
41 | + "description": "The string output of the diagnostic message by GHC",
|
|
42 | + "type": "array",
|
|
43 | + "items": {
|
|
44 | + "type": "string"
|
|
45 | + }
|
|
46 | + },
|
|
47 | + "hints": {
|
|
48 | + "description": "The suggested fixes",
|
|
49 | + "type": "array",
|
|
50 | + "items": {
|
|
51 | + "type": "string"
|
|
52 | + }
|
|
53 | + },
|
|
54 | + "reason" : {
|
|
55 | + "description": "The GHC flag that was responsible for the emission of the diagnostic message",
|
|
56 | + "oneOf": [
|
|
57 | + {
|
|
58 | + "type": "object",
|
|
59 | + "description": "The diagnostic message was controlled by one or more GHC flags",
|
|
60 | + "properties": {
|
|
61 | + "flags": {
|
|
62 | + "type": "array",
|
|
63 | + "items": {
|
|
64 | + "description": "The name of a GHC flag controlling the diagnostic message",
|
|
65 | + "type": "string"
|
|
66 | + },
|
|
67 | + "minItems": 1
|
|
68 | + }
|
|
69 | + },
|
|
70 | + "required": ["flags"]
|
|
71 | + },
|
|
72 | + {
|
|
73 | + "type": "object",
|
|
74 | + "description": "The diagnostic message was controlled by a GHC diagnostic message category",
|
|
75 | + "properties": {
|
|
76 | + "category": {
|
|
77 | + "description": "The name of the GHC diagnostic message category controlling the diagnostic message",
|
|
78 | + "type": "string"
|
|
79 | + }
|
|
80 | + },
|
|
81 | + "required": ["category"]
|
|
82 | + }
|
|
83 | + ]
|
|
84 | + }
|
|
85 | + },
|
|
86 | + |
|
87 | + "$comment": "NOTE: \"rendered\" is not a required field so that the schema is backward compatible with version 1.1. If you bump the schema version to 2.0 the please also add \"rendered\" to the \"required\" fields.",
|
|
88 | + "required": [
|
|
89 | + "version",
|
|
90 | + "ghcVersion",
|
|
91 | + "span",
|
|
92 | + "severity",
|
|
93 | + "code",
|
|
94 | + "message",
|
|
95 | + "hints"
|
|
96 | + ],
|
|
97 | + |
|
98 | + "additionalProperties": false,
|
|
99 | + "$defs": {
|
|
100 | + "span": {
|
|
101 | + "description": "The span of the diagnostic",
|
|
102 | + "type": "object",
|
|
103 | + "properties": {
|
|
104 | + "file": {
|
|
105 | + "description": "The file in which the diagnostic occurs",
|
|
106 | + "type": "string"
|
|
107 | + },
|
|
108 | + "start": {
|
|
109 | + "description": "The start location of the diagnostic",
|
|
110 | + "$ref": "#/$defs/location"
|
|
111 | + },
|
|
112 | + "end": {
|
|
113 | + "description": "The end location of the diagnostic",
|
|
114 | + "$ref": "#/$defs/location"
|
|
115 | + }
|
|
116 | + },
|
|
117 | + "required": [
|
|
118 | + "file",
|
|
119 | + "start",
|
|
120 | + "end"
|
|
121 | + ],
|
|
122 | + "additionalProperties": false
|
|
123 | + },
|
|
124 | + "location": {
|
|
125 | + "description": "A location in a text file",
|
|
126 | + "type": "object",
|
|
127 | + "properties": {
|
|
128 | + "line": {
|
|
129 | + "description": "The line number",
|
|
130 | + "type": "integer"
|
|
131 | + },
|
|
132 | + "column": {
|
|
133 | + "description": "The column number",
|
|
134 | + "type": "integer"
|
|
135 | + }
|
|
136 | + },
|
|
137 | + "required": [
|
|
138 | + "line",
|
|
139 | + "column"
|
|
140 | + ],
|
|
141 | + "additionalProperties": false
|
|
142 | + }
|
|
143 | + }
|
|
144 | +} |
... | ... | @@ -1428,7 +1428,7 @@ messages and in GHCi: |
1428 | 1428 | a new line.
|
1429 | 1429 | |
1430 | 1430 | The structure of the output is described by a `JSON Schema <https://json-schema.org/>`_.
|
1431 | - The schema can be downloaded :download:`here <diagnostics-as-json-schema-1_1.json>`.
|
|
1431 | + The schema can be downloaded :download:`here <diagnostics-as-json-schema-1_2.json>`.
|
|
1432 | 1432 | |
1433 | 1433 | .. ghc-flag:: -fdiagnostics-color=⟨always|auto|never⟩
|
1434 | 1434 | :shortdesc: Use colors in error messages
|
1 | -{"version":"1.1","ghcVersion":"ghc-9.13.20250529","span":{"file":"json.hs","start":{"line":9,"column":11},"end":{"line":9,"column":21}},"severity":"Error","code":48010,"message":["Empty list of alternatives in case expression"],"hints":["Perhaps you intended to use the \u2018EmptyCase\u2019 extension"]} |
|
1 | +{"rendered":"json.hs:9:11: error: [GHC-48010]\n Empty list of alternatives in case expression\n Suggested fix:\n Perhaps you intended to use the \u2018EmptyCase\u2019 extension\n","version":"1.1","ghcVersion":"ghc-9.13.20250627","span":{"file":"json.hs","start":{"line":9,"column":11},"end":{"line":9,"column":21}},"severity":"Error","code":48010,"message":["Empty list of alternatives in case expression"],"hints":["Perhaps you intended to use the \u2018EmptyCase\u2019 extension"]} |
1 | -{"version":"1.1","ghcVersion":"ghc-9.13.20250529","span":{"file":"json_warn.hs","start":{"line":4,"column":3},"end":{"line":4,"column":4}},"severity":"Warning","code":40910,"message":["Defined but not used: \u2018x\u2019"],"hints":[],"reason":{"flags":["unused-matches"]}}
|
|
2 | -{"version":"1.1","ghcVersion":"ghc-9.13.20250529","span":{"file":"json_warn.hs","start":{"line":7,"column":5},"end":{"line":7,"column":9}},"severity":"Warning","code":63394,"message":["In the use of \u2018head\u2019\n(imported from Prelude, but defined in GHC.Internal.List):\n\"This is a partial function, it throws an error on empty lists. Use pattern matching, 'Data.List.uncons' or 'Data.Maybe.listToMaybe' instead. Consider refactoring to use \"Data.List.NonEmpty\".\""],"hints":[],"reason":{"category":"x-partial"}} |
|
1 | +{"rendered":"json_warn.hs:4:3: warning: [GHC-40910] [-Wunused-matches (in -Wextra)]\n Defined but not used: \u2018x\u2019\n","version":"1.1","ghcVersion":"ghc-9.13.20250627","span":{"file":"json_warn.hs","start":{"line":4,"column":3},"end":{"line":4,"column":4}},"severity":"Warning","code":40910,"message":["Defined but not used: \u2018x\u2019"],"hints":[],"reason":{"flags":["unused-matches"]}}
|
|
2 | +{"rendered":"json_warn.hs:7:5: warning: [GHC-63394] [-Wx-partial (in -Wextended-warnings)]\n In the use of \u2018head\u2019\n (imported from Prelude, but defined in GHC.Internal.List):\n \"This is a partial function, it throws an error on empty lists. Use pattern matching, 'Data.List.uncons' or 'Data.Maybe.listToMaybe' instead. Consider refactoring to use \"Data.List.NonEmpty\".\"\n","version":"1.1","ghcVersion":"ghc-9.13.20250627","span":{"file":"json_warn.hs","start":{"line":7,"column":5},"end":{"line":7,"column":9}},"severity":"Warning","code":63394,"message":["In the use of \u2018head\u2019\n(imported from Prelude, but defined in GHC.Internal.List):\n\"This is a partial function, it throws an error on empty lists. Use pattern matching, 'Data.List.uncons' or 'Data.Maybe.listToMaybe' instead. Consider refactoring to use \"Data.List.NonEmpty\".\""],"hints":[],"reason":{"category":"x-partial"}} |