From 263ab9003095056fde4b1aa4ba6357269d6452d3 Mon Sep 17 00:00:00 2001 From: Fabrizio Ferrai Date: Mon, 19 Jan 2026 21:07:02 +0200 Subject: [PATCH 1/2] Censor user warnings according to the documentation --- README.md | 12 ++++---- src/Spago/Psa.purs | 21 ++++++++++++- .../spago-no-censor.yaml | 8 +++++ .../censor-user-defined-warning/spago.yaml | 11 +++++++ .../censor-user-defined-warning/src/Main.purs | 17 +++++++++++ test/Spago/Build.purs | 30 +++++++++++++++++++ 6 files changed, 92 insertions(+), 7 deletions(-) create mode 100644 test-fixtures/build/censor-user-defined-warning/spago-no-censor.yaml create mode 100644 test-fixtures/build/censor-user-defined-warning/spago.yaml create mode 100644 test-fixtures/build/censor-user-defined-warning/src/Main.purs diff --git a/README.md b/README.md index 5bfcb9c64..9ba2b2edd 100644 --- a/README.md +++ b/README.md @@ -1394,12 +1394,12 @@ workspace: # censor warnings if the code matches this code # - { byPrefix } values: # censor warnings if the warning's message - # starts with the given text + # starts with the given text. - CodeName # Note: when using `byPrefix`, use the `>` for block-string: # see https://yaml-multiline.info/ - byPrefix: > - "Data.Map"'s `Semigroup instance` + Data.Map's `Semigroup` instance # Specify whether to show statistics at the end of the compilation, # and how verbose they should be. @@ -1450,12 +1450,12 @@ package: # censor warnings if the code matches this code # - { byPrefix } values: # censor warnings if the warning's message - # starts with the given text + # starts with the given text. - CodeName # Note: when using `byPrefix`, use the `>` for block-string: # see https://yaml-multiline.info/ - byPrefix: > - "Data.Map"'s `Semigroup instance` + Data.Map's `Semigroup` instance # Convert compiler warnings for files in this package's src code # into errors that can fail the build. # Optional and defaults to false @@ -1518,12 +1518,12 @@ package: # censor warnings if the code matches this code # - { byPrefix } values: # censor warnings if the warning's message - # starts with the given text + # starts with the given text. - CodeName # Note: when using `byPrefix`, use the `>` for block-string: # see https://yaml-multiline.info/ - byPrefix: > - "Data.Map"'s `Semigroup instance` + Data.Map's `Semigroup` instance # Convert compiler warnings for files from this package's test code # into errors that can fail the build. # Optional and defaults to false diff --git a/src/Spago/Psa.purs b/src/Spago/Psa.purs index b51643c1d..bee80d515 100644 --- a/src/Spago/Psa.purs +++ b/src/Spago/Psa.purs @@ -189,8 +189,27 @@ shouldPrintWarning = case _ of let tests = arr <#> case _ of ByCode c -> \code _ -> c == code - ByMessagePrefix prefix -> \_ msg -> isJust $ String.stripPrefix (String.Pattern $ String.trim prefix) (String.trim msg) + ByMessagePrefix prefix -> \code msg -> + let + trimmedPrefix = String.trim prefix + trimmedMsg = String.trim msg + -- Try direct match first + directMatch = isJust $ String.stripPrefix (String.Pattern trimmedPrefix) trimmedMsg + -- For UserDefinedWarning, also try matching without the compiler preamble + strippedMatch = code == "UserDefinedWarning" + && isJust (String.stripPrefix (String.Pattern trimmedPrefix) (stripUserWarningPreamble trimmedMsg)) + in + directMatch || strippedMatch -- We return `true` to print the warning. -- If an element was found (i.e. `Just` is returned), then one of the tests succeeded, -- so we should not print the warning and return false here. \code msg -> isNothing $ NonEmptyArray.find (\f -> f code msg) tests + +-- | Strip the preamble that the PureScript compiler adds to UserDefinedWarning messages. +-- | This allows byPrefix to match just the user-defined content. +stripUserWarningPreamble :: String -> String +stripUserWarningPreamble msg = + let preamble = "A custom warning occurred while solving type class constraints:" + in case String.stripPrefix (String.Pattern preamble) msg of + Just rest -> String.trim rest + Nothing -> msg diff --git a/test-fixtures/build/censor-user-defined-warning/spago-no-censor.yaml b/test-fixtures/build/censor-user-defined-warning/spago-no-censor.yaml new file mode 100644 index 000000000..edaff3c48 --- /dev/null +++ b/test-fixtures/build/censor-user-defined-warning/spago-no-censor.yaml @@ -0,0 +1,8 @@ +package: + name: censor-user-warning-test + dependencies: + - prelude + +workspace: + packageSet: + registry: 41.5.0 diff --git a/test-fixtures/build/censor-user-defined-warning/spago.yaml b/test-fixtures/build/censor-user-defined-warning/spago.yaml new file mode 100644 index 000000000..5b9215f6e --- /dev/null +++ b/test-fixtures/build/censor-user-defined-warning/spago.yaml @@ -0,0 +1,11 @@ +package: + name: censor-user-warning-test + dependencies: + - prelude + build: + censorProjectWarnings: + - byPrefix: "This is a custom warning" + +workspace: + packageSet: + registry: 41.5.0 diff --git a/test-fixtures/build/censor-user-defined-warning/src/Main.purs b/test-fixtures/build/censor-user-defined-warning/src/Main.purs new file mode 100644 index 000000000..9613016ec --- /dev/null +++ b/test-fixtures/build/censor-user-defined-warning/src/Main.purs @@ -0,0 +1,17 @@ +module Main where + +import Prelude +import Prim.TypeError (class Warn, Text) + +-- A type class with a Warn constraint that triggers a UserDefinedWarning +class MyClass a where + myFunction :: a -> a + +instance warnedInstance :: + ( Warn (Text "This is a custom warning that should be censored") + ) => MyClass Int where + myFunction = identity + +-- Using the instance triggers the warning at compile time +main :: Int +main = myFunction 42 diff --git a/test/Spago/Build.purs b/test/Spago/Build.purs index cc780fe87..884e2e6af 100644 --- a/test/Spago/Build.purs +++ b/test/Spago/Build.purs @@ -143,6 +143,36 @@ spec = Spec.around withTempDir do , result: isRight } + Spec.it "should censor UserDefinedWarning with byPrefix matching just the user content" \{ spago, fixture, testCwd } -> do + FS.copyTree { src: fixture "build/censor-user-defined-warning", dst: testCwd "." } + + let + warningTexts = + [ escapePathInErrMsg [ "src", "Main.purs" ] + , "UserDefinedWarning" + , "A custom warning occurred while solving type class constraints" + , "This is a custom warning that should be censored" + ] + shouldHaveWarning = assertWarning warningTexts true + shouldNotHaveWarning = assertWarning warningTexts false + + -- First, verify the warning IS censored with byPrefix matching user content + spago [ "build" ] >>= check + { stdout: mempty + , stderr: shouldNotHaveWarning + , result: isRight + } + + -- Now remove the censor config and verify the warning DOES appear + FS.unlink $ testCwd "spago.yaml" + FS.moveSync { src: testCwd "spago-no-censor.yaml", dst: testCwd "spago.yaml" } + rmRf $ testCwd "output" + spago [ "build" ] >>= check + { stdout: mempty + , stderr: shouldHaveWarning + , result: isRight + } + Spec.describe "lockfile" do Spec.it "building with a lockfile doesn't need the Registry repo" \{ spago, fixture, testCwd } -> do spago [ "init", "--name", "aaa", "--package-set", "33.0.0" ] >>= shouldBeSuccess From 14de49c3cf14da0d3bb3b0884f8e3a9437baa252 Mon Sep 17 00:00:00 2001 From: Fabrizio Ferrai Date: Thu, 22 Jan 2026 10:23:05 +0200 Subject: [PATCH 2/2] Formatting --- src/Spago/Psa.purs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Spago/Psa.purs b/src/Spago/Psa.purs index bee80d515..2c76edcc4 100644 --- a/src/Spago/Psa.purs +++ b/src/Spago/Psa.purs @@ -209,7 +209,9 @@ shouldPrintWarning = case _ of -- | This allows byPrefix to match just the user-defined content. stripUserWarningPreamble :: String -> String stripUserWarningPreamble msg = - let preamble = "A custom warning occurred while solving type class constraints:" - in case String.stripPrefix (String.Pattern preamble) msg of - Just rest -> String.trim rest - Nothing -> msg + let + preamble = "A custom warning occurred while solving type class constraints:" + in + case String.stripPrefix (String.Pattern preamble) msg of + Just rest -> String.trim rest + Nothing -> msg