From 284e97ce909321d94488e7c35ec886d20203cf1d Mon Sep 17 00:00:00 2001 From: Gilbert Ramirez Date: Sun, 25 Jan 2026 14:23:57 -0600 Subject: [PATCH] toSnippet shouldn't crash if the error has no source code Fixes #360 A "MODULE NOT FOUND" error may be due to the default "import" statements the compiler adds to Gren source code (like, "import Basics"), if gren.json doesn't contain "gren-lang/core". In this case, there is no faulty source code region to report, so toSnippet should recognize this and avoid crashing when trying to render it. --- compiler/src/Reporting/Render/Code.hs | 23 +++++++++---- gren.cabal | 6 +++- tests/Reporting/Error/ImportSpec.hs | 49 +++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 tests/Reporting/Error/ImportSpec.hs diff --git a/compiler/src/Reporting/Render/Code.hs b/compiler/src/Reporting/Render/Code.hs index f4998406..e608f183 100644 --- a/compiler/src/Reporting/Render/Code.hs +++ b/compiler/src/Reporting/Render/Code.hs @@ -42,13 +42,22 @@ toSource source = -- CODE FORMATTING toSnippet :: Source -> A.Region -> Maybe A.Region -> (D.Doc, D.Doc) -> D.Doc -toSnippet source region highlight (preHint, postHint) = - D.vcat - [ preHint, - "", - render source region highlight, - postHint - ] +toSnippet source region@(A.Region (A.Position startLine _) (A.Position _ _)) highlight (preHint, postHint) = + if startLine > 0 + then + D.vcat + [ preHint, + "", + render source region highlight, + postHint + ] + else + -- The region doesn't point to actual source code. Don't render it. + D.vcat + [ preHint, + "", + postHint + ] toPair :: Source -> A.Region -> A.Region -> (D.Doc, D.Doc) -> (D.Doc, D.Doc, D.Doc) -> D.Doc toPair source r1 r2 (oneStart, oneEnd) (twoStart, twoMiddle, twoEnd) = diff --git a/gren.cabal b/gren.cabal index af55bd25..ab4e0093 100644 --- a/gren.cabal +++ b/gren.cabal @@ -254,13 +254,17 @@ Test-Suite gren-tests Parse.UnderscorePatternSpec Parse.MultilineStringSpec Parse.DeclSpec + Reporting.Error.ImportSpec Build-Depends: gren:common, base >= 4.19 && <5, + containers >= 0.6 && < 0.7, utf8-string, bytestring >= 0.11 && < 0.12, - hspec >= 2.7.10 && < 3 + hspec >= 2.7.10 && < 3, + prettyprinter >= 1.7.1 && < 2, + text >= 2.1.2 && < 3 Build-Tool-Depends: hspec-discover:hspec-discover >= 2.7.10 && < 3 diff --git a/tests/Reporting/Error/ImportSpec.hs b/tests/Reporting/Error/ImportSpec.hs new file mode 100644 index 00000000..0ada2c72 --- /dev/null +++ b/tests/Reporting/Error/ImportSpec.hs @@ -0,0 +1,49 @@ +module Reporting.Error.ImportSpec (spec) where + +import Data.Set qualified as Set +import Data.Text as T +import Data.Text.Encoding as T +import Data.Utf8 qualified as Utf8 +import Prettyprinter qualified as P +import Prettyprinter.Render.Text (renderStrict) +import Reporting.Annotation qualified as A +import Reporting.Error.Import qualified as Import +import Reporting.Render.Code qualified as Code +import Reporting.Report qualified as Report +import Test.Hspec (Spec, describe, it) + +spec :: Spec +spec = do + describe "Import error reporting" $ do + {- + When "gren-lang/core" module is not listed in gren.json, the + default imports that the compiler inserts into the code + fail, but there is no source code region to report. + We want to ensure the reporting code doesn't crash, and + actually reports that modules like Basics (and others) are reported + as not found. + -} + it "Give proper error if default package dependencies are not found" $ do + let -- Empty source code + source = Code.toSource (T.encodeUtf8 (T.pack "")) + + -- The "Module Not Found" Error + err = + Import.Error + { -- IMPORTANT: The region here is zero, not pointing to any + -- possible lines of source code. This happens when + -- "import Basics" is added by default by the compiler, without + -- it appearing in the actual source code. + Import._region = A.Region (A.Position 0 0) (A.Position 0 0), + Import._import = Utf8.fromChars "foo", + Import._unimported = Set.singleton (Utf8.fromChars "Basics"), + Import._problem = Import.NotFound + } + + -- Create the report + report = Import.toReport source err + + -- Convert the Prettyprinter Doc to a Data.Text + messageText = renderStrict (P.layoutCompact $ Report._message report) + in -- Does it have one of the missing modules reported in it? + T.isInfixOf (T.pack "Basics") messageText