<div dir="auto"><div style="font-family:sans-serif;font-size:12.8px" dir="auto"><div style="width:328px;margin:16px 0px"><div><div><font size="-1"><font face="Verdana">Hi, lately i am being collaborated in the haskell-ide-engine (hie) repo and one of the issues i get to fix was related with the parsing of ghc errors.<br>It turns out that delimiters of terms in errors are different in windows (`term') and *nix (‘term’) systems and that drive to parse errors.<br>Quite code actions and diagnostics are based in parsing them and they were broken in windows.<br>I am afraid that the code is very brittle and close to human readable error messages. the actual code look like this:<br><br></font></font><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">-- | Extract a term from a compiler message.</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">-- It looks for terms delimited between '‘' and '’' falling back to '`' and '\''</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">-- (the used ones in Windows systems).</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">extractTerm :: T.Text -> T.Text</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">extractTerm txt =</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">  case extract '‘' '’' txt of</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">    ""  -> extract '`' '\'' txt -- Needed for windows</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">    term -> term</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">  where extract b e = T.dropWhile (== b)</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">                    . T.dropWhileEnd (== e)</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">                    . T.dropAround (\c -> c /= b && c /= e)

</font></font>
</pre><font size="-1"><font face="Verdana">or<br><br></font></font><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">extractImportableTerm :: T.Text -> Maybe (T.Text, SymbolImport SymbolType)</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">extractImportableTerm dirtyMsg = do</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">  (n, s) <- extractedTerm</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">  let n' = T.strip n</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">  return (n', s)</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">  where</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">    importMsg = S.headMay</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">      -- Get rid of the rename suggestion parts</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">      $ T.splitOn "Perhaps you meant "</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">      $ T.replace "\n" " "</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">      -- Get rid of trailing/leading whitespace on each individual line</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">      $ T.unlines</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">      $ map T.strip</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">      $ T.lines</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">      $ T.replace "* " "" -- Needed for Windows</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">      $ T.replace "• " "" dirtyMsg</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">    extractTerm prefix symTy =</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">      importMsg</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">          >>= T.stripPrefix prefix</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">          >>= \name -> Just (name, Import symTy)</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">    extractType b =</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">      extractTerm ("Not in scope: type constructor or class " <> b) Type</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">    extractedTerm = asum</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">      [ extractTerm "Variable not in scope: " Symbol</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">      , extractType "‘"</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">      , extractType "`" -- Needed for windows</font></font></pre><pre style="white-space:pre-wrap"><font size="-1"><font face="Verdana">      , extractTerm "Data constructor not in scope: " Constructor]</font></font></pre><font size="-1"><font face="Verdana"><br>It is clearly unsatisfactory but hard to improve without changing the messages to make it more structured.<br>Moreover any legitimate change on errors to make it better will likely break it.<br><br>After exposing my worries in the hie irc channel, @mpickering pointed out that it is already a proposal to improve error messages:<br></font></font><br><a href="https://github.com/bgamari/ghc-proposals/blob/rich-errors-proposal/proposals/0000-rich-errors-proposal.rst" style="text-decoration-line:none;color:rgb(66,133,244)">https://github.com/bgamari/ghc-proposals/blob/rich-errors-proposal/proposals/0000-rich-errors-proposal.rst</a><br><br>that nicely will improve the state of things.<br><br>Otoh there are already a way to output ghc errors as json (see <a href="https://gitlab.haskell.org/ghc/ghc/issues/13190" style="text-decoration-line:none;color:rgb(66,133,244)">https://gitlab.haskell.org/ghc/ghc/issues/13190</a>). It contains valuable info about the error in specific fields but the message itself is in plain text.<br>So merging both features will let tools to handle compiler errors without use the ghc api directly if needed.<br><br>what is the status of the proposal? hie an other tooling developers will welcome it very heartly.<br><br>Thanks in advance!<br></div></div></div></div></div>