Skip to content

Commit 26ff517

Browse files
authored
In PSA output label warnings and errors as such (#1277)
1 parent a7827be commit 26ff517

File tree

13 files changed

+192
-21
lines changed

13 files changed

+192
-21
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ Other improvements:
2727
cached locally.
2828
- `spago publish` now allows to publish a package with some test (but only
2929
test!) dependencies not present in the registry.
30+
- errors and warnings are now explicitly labeled as "ERROR" and "WARNING" in
31+
Spago build output.
3032
- always using forward slash as path separator in lockfile, regardless of the
3133
platform, so that the lockfile doesn't keep changing when team members run
3234
Spago on different platforms.

src/Spago/Psa/Printer.purs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
-- Copyright © Nathan Faubion
66
-- https://opensource.org/license/mit/
77
module Spago.Psa.Printer
8-
( renderWarning
9-
, renderError
10-
, renderStats
8+
( renderStats
119
, renderVerboseStats
1210
, printDefaultOutputToErr
1311
, printJsonOutputToOut
@@ -50,11 +48,11 @@ printJsonOutputToOut output = do
5048
printDefaultOutputToErr :: PsaArgs -> Output -> Effect Unit
5149
printDefaultOutputToErr options output = do
5250
forWithIndex_ output.warnings \i warning -> do
53-
Console.error $ printDoc (renderWarning lenWarnings (i + 1) warning)
51+
Console.error $ printDoc (renderCitation Warn lenWarnings (i + 1) warning)
5452
Console.error ""
5553

5654
forWithIndex_ output.errors \i error -> do
57-
Console.error $ printDoc (renderError lenErrors (i + 1) error)
55+
Console.error $ printDoc (renderCitation Err lenErrors (i + 1) error)
5856
Console.error ""
5957

6058
Console.error $ printDoc (renderStats' output.stats)
@@ -70,17 +68,21 @@ printDefaultOutputToErr options output = do
7068
Core.CompactStats -> renderStats
7169
Core.VerboseStats -> renderVerboseStats
7270

73-
renderWarning :: Int -> Int -> PsaAnnotedError -> D.Doc Ansi.GraphicsParam
74-
renderWarning = renderWrapper Ansi.BrightYellow
71+
data Citation = Warn | Err
7572

76-
renderError :: Int -> Int -> PsaAnnotedError -> D.Doc Ansi.GraphicsParam
77-
renderError = renderWrapper Ansi.BrightRed
73+
citationColor :: Citation -> Ansi.Color
74+
citationColor Warn = Ansi.BrightYellow
75+
citationColor Err = Ansi.BrightRed
7876

79-
renderWrapper :: Ansi.Color -> Int -> Int -> PsaAnnotedError -> D.Doc Ansi.GraphicsParam
80-
renderWrapper color total index { error, path, position, source, message } =
77+
citationLabel :: Citation -> String
78+
citationLabel Warn = "WARNING"
79+
citationLabel Err = "ERROR"
80+
81+
renderCitation :: Citation -> Int -> Int -> PsaAnnotedError -> D.Doc Ansi.GraphicsParam
82+
renderCitation cit total index { error, path, position, source, message } =
8183
D.foldWithSeparator (D.break <> D.break)
8284
[ D.words $
83-
[ renderStatus color total index error.errorCode
85+
[ renderStatus cit total index error.errorCode
8486
, renderPath path error.moduleName <> foldMap renderPosition position
8587
]
8688
, D.indent $ D.lines
@@ -92,9 +94,11 @@ renderWrapper color total index { error, path, position, source, message } =
9294
toLines :: String -> D.Doc Ansi.GraphicsParam
9395
toLines = D.lines <<< map D.text <<< Str.split (Str.Pattern "\n")
9496

95-
renderStatus :: Ansi.Color -> Int -> Int -> String -> D.Doc Ansi.GraphicsParam
96-
renderStatus color total index code =
97-
DA.foreground color $ D.text $ "[" <> show index <> "/" <> show total <> " " <> code <> "]"
97+
renderStatus :: Citation -> Int -> Int -> String -> D.Doc Ansi.GraphicsParam
98+
renderStatus cit total index code =
99+
DA.foreground (citationColor cit)
100+
$ D.text
101+
$ "[" <> citationLabel cit <> " " <> show index <> "/" <> show total <> " " <> code <> "]"
98102

99103
renderModuleName :: Maybe String -> D.Doc Ansi.GraphicsParam
100104
renderModuleName Nothing = DA.dim $ D.text "(unknown module)"
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
Reading Spago workspace configuration...
2+
3+
✓ Selecting package to build: foo
4+
5+
Downloading dependencies...
6+
Building...
7+
[1 of 2] Compiling Foo
8+
[2 of 2] Compiling Main
9+
[ERROR 1/2 TypesDoNotUnify] src/Foo.purs:4:5
10+
11+
4 x = "nope"
12+
^^^^^^
13+
14+
Could not match type
15+
String
16+
with type
17+
Int
18+
while checking that type String
19+
is at least as general as type Int
20+
while checking that expression "nope"
21+
has type Int
22+
in value declaration x
23+
24+
[ERROR 2/2 TypesDoNotUnify] src/Main.purs:10:7
25+
26+
10 log 42
27+
^^
28+
29+
Could not match type
30+
Int
31+
with type
32+
String
33+
while checking that type Int
34+
is at least as general as type String
35+
while checking that expression 42
36+
has type String
37+
in value declaration main
38+
39+
Src Lib All
40+
Warnings 0 0 0
41+
Errors 2 0 2
42+
43+
✘ Failed to build.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package:
2+
name: foo
3+
dependencies:
4+
- console
5+
- effect
6+
- prelude
7+
8+
workspace:
9+
packageSet:
10+
registry: 41.5.0
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module Foo where
2+
3+
x :: Int
4+
x = "nope"
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module Main where
2+
3+
import Prelude
4+
5+
import Effect
6+
import Effect.Console (log)
7+
8+
main :: Effect Unit
9+
main = do
10+
log 42
11+
pure unit
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
Reading Spago workspace configuration...
2+
3+
✓ Selecting package to build: foo
4+
5+
Downloading dependencies...
6+
Building...
7+
[1 of 1] Compiling Main
8+
[WARNING 1/4 ImplicitImport] src/Main.purs:3:1
9+
10+
3 import Prelude
11+
^^^^^^^^^^^^^^
12+
13+
Module Prelude has unspecified imports, consider using the explicit form:
14+
import Prelude (Unit, pure, unit)
15+
16+
[WARNING 2/4 ImplicitImport] src/Main.purs:5:1
17+
18+
5 import Effect
19+
^^^^^^^^^^^^^
20+
21+
Module Effect has unspecified imports, consider using the explicit form:
22+
import Effect (Effect)
23+
24+
[WARNING 3/4 UnusedImport] src/Main.purs:6:1
25+
26+
6 import Effect.Console (log)
27+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
28+
29+
The import of Effect.Console is redundant
30+
31+
[WARNING 4/4 UnusedName] src/Main.purs:10:7
32+
33+
10 let unusedVar = 1
34+
^^^^^^^^^^^^^
35+
36+
Name unusedVar was introduced but not used.
37+
in value declaration main
38+
39+
Src Lib All
40+
Warnings 4 0 4
41+
Errors 0 0 0
42+
43+
✓ Build succeeded.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package:
2+
name: foo
3+
dependencies:
4+
- console
5+
- effect
6+
- prelude
7+
8+
workspace:
9+
packageSet:
10+
registry: 41.5.0
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module Main where
2+
3+
import Prelude
4+
5+
import Effect
6+
import Effect.Console (log)
7+
8+
main :: Effect Unit
9+
main = do
10+
let unusedVar = 1
11+
pure unit

test/Prelude.purs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,5 +396,11 @@ escapePathInErrMsg = case Process.platform of
396396
assertWarning :: forall m. MonadThrow Error m => Array String -> Boolean -> String -> m Unit
397397
assertWarning paths shouldHave stdErr = do
398398
when (not $ Array.all (\exp -> shouldHave == (String.contains (Pattern exp) stdErr)) paths) do
399-
Assert.fail $ "STDERR contained one or more texts:\n" <> show paths <> "\n\nStderr was:\n" <> stdErr
399+
Assert.fail
400+
$ "STDERR "
401+
<> (if shouldHave then "did not contain" else "contained")
402+
<> " one or more texts:\n"
403+
<> show paths
404+
<> "\n\nStderr was:\n"
405+
<> stdErr
400406

test/Spago/Build.purs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module Test.Spago.Build where
33
import Test.Prelude
44

55
import Data.Foldable (fold)
6+
import Data.String as String
67
import Node.FS.Aff as FSA
78
import Node.Path as Path
89
import Node.Platform as Platform
@@ -211,6 +212,32 @@ spec = Spec.around withTempDir do
211212
spago [ "build" ] >>= shouldBeSuccessErr (fixture "build/migrate-config/migrated-output.txt")
212213
checkFixture "spago.yaml" (fixture "build/migrate-config/migrated-spago.yaml")
213214

215+
Spec.it "#1148: outputs errors and warnings after build" \{ spago, fixture } -> do
216+
let
217+
shouldBeSuccessErr' = checkOutputsWithPathSeparatorPatchErr isRight
218+
shouldBeFailureErr' = checkOutputsWithPathSeparatorPatchErr isLeft
219+
220+
checkOutputsWithPathSeparatorPatchErr result expectedFixture =
221+
checkOutputs'
222+
{ stdoutFile: Nothing
223+
, stderrFile: Just $ fixture expectedFixture
224+
, result
225+
, sanitize:
226+
String.trim
227+
>>> String.replaceAll (String.Pattern $ "src\\") (String.Replacement "src/")
228+
>>> String.replaceAll (String.Pattern $ "\r\n") (String.Replacement "\n")
229+
}
230+
231+
FS.copyTree { src: fixture "build/1148-warnings-diff-errors", dst: "." }
232+
233+
liftEffect $ Process.chdir "errors"
234+
spago [ "install" ] >>= shouldBeSuccess
235+
spago [ "build" ] >>= shouldBeFailureErr' "build/1148-warnings-diff-errors/errors/expected-stderr.txt"
236+
237+
liftEffect $ Process.chdir "../warnings"
238+
spago [ "install" ] >>= shouldBeSuccess
239+
spago [ "build" ] >>= shouldBeSuccessErr' "build/1148-warnings-diff-errors/warnings/expected-stderr.txt"
240+
214241
Pedantic.spec
215242

216243
Monorepo.spec

test/Spago/Build/Monorepo.purs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,8 @@ spec = Spec.describe "monorepo" do
142142
FS.copyTree { src: fixture "monorepo/strict-true-uncensored-warnings", dst: "." }
143143
let
144144
errs =
145-
[ "[1/2 UnusedName] " <> escapePathInErrMsg [ "package-b", "src", "Main.purs:6:13" ]
146-
, "[2/2 UnusedName] " <> escapePathInErrMsg [ "package-b", "test", "Main.purs:6:13" ]
145+
[ "[ERROR 1/2 UnusedName] " <> escapePathInErrMsg [ "package-b", "src", "Main.purs:6:13" ]
146+
, "[ERROR 2/2 UnusedName] " <> escapePathInErrMsg [ "package-b", "test", "Main.purs:6:13" ]
147147
]
148148
hasUnusedWarningError = assertWarning errs true
149149
spago [ "build" ] >>= check { stdout: mempty, stderr: hasUnusedWarningError, result: isLeft }

test/Spago/Test.purs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ spec = Spec.around withTempDir do
6060
FS.mkdirp "subpackage/test"
6161
FS.writeTextFile "subpackage/src/Main.purs" (Init.srcMainTemplate "Subpackage.Main")
6262

63-
-- We write a file into the current working directory.
63+
-- We write a file into the current working directory.
6464
-- The subpackage test will read the given file without changing its directory
6565
-- and log its content as its output.
6666
let textFilePath = "foo.txt"
@@ -130,8 +130,8 @@ spec = Spec.around withTempDir do
130130
let
131131
exp =
132132
case Process.platform of
133-
Just Platform.Win32 -> "[1/1 UnusedName] test\\Test\\Main.purs:10:5"
134-
_ -> "[1/1 UnusedName] test/Test/Main.purs:10:5"
133+
Just Platform.Win32 -> "[WARNING 1/1 UnusedName] test\\Test\\Main.purs:10:5"
134+
_ -> "[WARNING 1/1 UnusedName] test/Test/Main.purs:10:5"
135135
hasUnusedNameWarningError stdErr = do
136136

137137
unless (String.contains (String.Pattern exp) stdErr) do

0 commit comments

Comments
 (0)