From 534df0dec57a157a580eac74e6569297e8c6de65 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 30 Mar 2023 01:56:36 -0500 Subject: [PATCH 01/78] Vendor in psa & psa-utils --- spaghetto/src/Spago/Psa.purs | 349 +++++++++++++++++++ spaghetto/src/Spago/Psa/Output.purs | 274 +++++++++++++++ spaghetto/src/Spago/Psa/Printer.purs | 135 +++++++ spaghetto/src/Spago/Psa/Printer/Default.purs | 186 ++++++++++ spaghetto/src/Spago/Psa/Printer/Json.purs | 21 ++ spaghetto/src/Spago/Psa/Types.purs | 217 ++++++++++++ spaghetto/src/Spago/Psa/Util.purs | 30 ++ 7 files changed, 1212 insertions(+) create mode 100644 spaghetto/src/Spago/Psa.purs create mode 100644 spaghetto/src/Spago/Psa/Output.purs create mode 100644 spaghetto/src/Spago/Psa/Printer.purs create mode 100644 spaghetto/src/Spago/Psa/Printer/Default.purs create mode 100644 spaghetto/src/Spago/Psa/Printer/Json.purs create mode 100644 spaghetto/src/Spago/Psa/Types.purs create mode 100644 spaghetto/src/Spago/Psa/Util.purs diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs new file mode 100644 index 000000000..84b4859fa --- /dev/null +++ b/spaghetto/src/Spago/Psa.purs @@ -0,0 +1,349 @@ +-- A majority of this code was copied from +-- - https://github.com/natefaubion/purescript-psa +-- +-- To fullfil license requirements +-- Copyright © Nathan Faubion +-- https://opensource.org/license/mit/ +module Spago.Psa where + +import Prelude + +import Data.Argonaut.Core (stringify) +import Data.Argonaut.Decode (decodeJson) +import Data.Argonaut.Encode (encodeJson) +import Data.Argonaut.Parser (jsonParser) +import Data.Array as Array +import Data.DateTime (DateTime) +import Data.DateTime.Instant (toDateTime) +import Data.Either (Either(..)) +import Data.Foldable (foldr, fold, for_) +import Data.Maybe (Maybe(..), maybe) +import Data.Set as Set +import Data.String as Str +import Data.Traversable (traverse) +import Data.Tuple (Tuple(..)) +import Data.Version as Version +import Effect (Effect) +import Effect.Console as Console +import Effect.Exception (catchException, throw, throwException) +import Effect.Now (now) +import Effect.Ref as Ref +import Foreign.Object as FO +import Node.ChildProcess as Child +import Node.Encoding as Encoding +import Node.FS.Stats as Stats +import Node.FS.Sync as File +import Node.Path as Path +import Node.Platform (Platform(Win32)) +import Node.Process as Process +import Node.Stream as Stream +import Partial.Unsafe (unsafePartial) +import Psa (PsaOptions, StatVerbosity(..), parsePsaResult, parsePsaError, encodePsaError, output) +import Psa.Printer.Default as DefaultPrinter +import Psa.Printer.Json as JsonPrinter + +foreign import version :: String + +defaultOptions :: PsaOptions +defaultOptions = + { ansi: true + , censorWarnings: false + , censorLib: false + , censorSrc: false + , censorCodes: Set.empty + , filterCodes: Set.empty + , statVerbosity: CompactStats + , libDirs: [] + , strict: false + , cwd: "" + } + +type ParseOptions = + { extra :: Array String + , opts :: PsaOptions + , purs :: String + , showSource :: Boolean + , stash :: Boolean + , stashFile :: String + , jsonErrors :: Boolean + } + +parseOptions + :: PsaOptions + -> Array String + -> Effect ParseOptions +parseOptions opts args = + defaultLibDir <$> + Array.foldM parse + { extra: [] + , purs: "purs" + , showSource: true + , stash: false + , stashFile: ".psa-stash" + , jsonErrors: false + , opts + } + args + where + parse p arg + | arg == "--version" || arg == "-v" = + Console.log version *> Process.exit 0 + + | arg == "--help" || arg == "-h" = + Console.log usage *> Process.exit 0 + + | arg == "--stash" = + pure p { stash = true } + + | arg == "--json-errors" = + pure p { jsonErrors = true } + + | arg == "--no-source" = + pure p { showSource = false } + + | arg == "--no-colors" || arg == "--monochrome" = + pure p { opts = p.opts { ansi = false } } + + | arg == "--verbose-stats" = + pure p { opts = p.opts { statVerbosity = VerboseStats } } + + | arg == "--censor-stats" = + pure p { opts = p.opts { statVerbosity = NoStats } } + + | arg == "--strict" = + pure p { opts = p.opts { strict = true } } + + | arg == "--censor-warnings" = + pure p { opts = p.opts { censorWarnings = true } } + + | arg == "--censor-lib" = + pure p { opts = p.opts { censorLib = true } } + + | arg == "--censor-src" = + pure p { opts = p.opts { censorSrc = true } } + + | isPrefix "--censor-codes=" arg = + pure p { opts = p.opts { censorCodes = foldr Set.insert p.opts.censorCodes (Str.split (Str.Pattern ",") (Str.drop 15 arg)) } } + + | isPrefix "--filter-codes=" arg = + pure p { opts = p.opts { filterCodes = foldr Set.insert p.opts.filterCodes (Str.split (Str.Pattern ",") (Str.drop 15 arg)) } } + + | isPrefix "--is-lib=" arg = + pure p { opts = p.opts { libDirs = Array.snoc p.opts.libDirs (Str.drop 9 arg) } } + + | isPrefix "--purs=" arg = + pure p { purs = Str.drop 7 arg } + + | isPrefix "--stash=" arg = + pure p { stash = true, stashFile = Str.drop 8 arg } + + | otherwise = pure p { extra = Array.snoc p.extra arg } + + isPrefix s str = + case Str.indexOf (Str.Pattern s) str of + Just x | x == 0 -> true + _ -> false + + defaultLibDir x + | Array.length x.opts.libDirs == 0 = + x { opts = x.opts { libDirs = [ "bower_components", ".spago" ] } } + | otherwise = x + +main :: Effect Unit +main = void do + cwd <- Process.cwd + argv <- Array.drop 2 <$> Process.argv + + { extra + , opts + , purs + , showSource + , stash + , stashFile + , jsonErrors + } <- parseOptions (defaultOptions { cwd = cwd }) argv + + libDirs <- traverse (Path.resolve [ cwd ] >>> map (_ <> Path.sep)) opts.libDirs + let + opts' = opts { libDirs = libDirs } + args = Array.cons "compile" $ Array.cons "--json-errors" extra + + stashData <- + if stash then readStashFile stashFile + else emptyStash + + readPursVersion purs \pursVer -> do + let + outputStream = + -- As of 0.14.0, JSON errors/warnings are written to stdout, but + -- beforehand they were written to stderr. + -- + -- We need to use Tuple like this because prerelease versions compare + -- less than normal versions with the same major, minor, and patch + -- numbers according to the semver spec. + if Tuple (Version.major pursVer) (Version.minor pursVer) >= Tuple 0 14 then Stdout + else Stderr + spawn' outputStream purs args \pursResult -> do + for_ (Str.split (Str.Pattern "\n") pursResult.output) \err -> + case jsonParser err >>= decodeJson >>= parsePsaResult of + Left _ -> Console.error err + Right out -> do + files <- Ref.new FO.empty + let + loadLinesImpl = if showSource then loadLines files else loadNothing + filenames = insertFilenames (insertFilenames Set.empty out.errors) out.warnings + merged <- mergeWarnings filenames stashData.date stashData.stash out.warnings + when stash $ writeStashFile stashFile merged + out' <- output loadLinesImpl opts' out { warnings = merged } + if jsonErrors then JsonPrinter.print out' + else DefaultPrinter.print opts' out' + if FO.isEmpty out'.stats.allErrors then Process.exit pursResult.exitCode + else Process.exit 1 + + where + insertFilenames = foldr \x s -> maybe s (flip Set.insert s) x.filename + loadNothing _ _ = pure Nothing + + spawn' outputStream cmd args onExit = do + let + stdio = + case outputStream of + Stdout -> [ Just Child.Pipe, Just Child.Pipe, unsafePartial (Array.unsafeIndex Child.inherit 2) ] + Stderr -> [ Just Child.Pipe, unsafePartial (Array.unsafeIndex Child.inherit 1), Just Child.Pipe ] + + child <- Child.spawn cmd args Child.defaultSpawnOptions { stdio = stdio } + buffer <- Ref.new "" + fillBuffer buffer $ + case outputStream of + Stdout -> Child.stdout child + Stderr -> Child.stderr child + Child.onExit child \status -> + case status of + Child.Normally n -> do + output <- Ref.read buffer + onExit { output, exitCode: n } + Child.BySignal s -> do + Console.error (show s) + Process.exit 1 + Child.onError child (retryWithCmd outputStream cmd args onExit) + + fillBuffer buffer stream = + Stream.onDataString stream Encoding.UTF8 \chunk -> + Ref.modify_ (_ <> chunk) buffer + + readPursVersion :: String -> (Version.Version -> Effect Unit) -> Effect Unit + readPursVersion purs cb = do + spawn' Stdout purs [ "--version" ] \{ output } -> do + let verStr = Str.takeWhile (_ /= Str.codePointFromChar ' ') $ Str.trim output + case Version.parseVersion verStr of + Right v -> + cb v + Left err -> do + throw $ fold + [ "Unable to parse the version from `purs`. (Saw: " + , verStr + , "). Please check that the right executable is on your PATH." + ] + + retryWithCmd outputStream cmd args onExit err + | err.code == "ENOENT" = do + -- On windows, if the executable wasn't found, try adding .cmd + if Process.platform == Just Win32 then + case Str.stripSuffix (Str.Pattern ".cmd") cmd of + Nothing -> spawn' outputStream (cmd <> ".cmd") args onExit + Just bareCmd -> throw $ "`" <> bareCmd <> "` executable not found. (nor `" <> cmd <> "`)" + else + throw $ "`" <> cmd <> "` executable not found." + | otherwise = + throwException (Child.toStandardError err) + + isEmptySpan filename pos = + filename == "" || + pos.startLine == 0 && pos.endLine == 0 + && pos.startColumn == 0 + && pos.endColumn == 0 + + -- TODO: Handle exceptions + loadLines files filename pos + | isEmptySpan filename pos = pure Nothing + | otherwise = catchException (const (pure Nothing)) do + cache <- FO.lookup filename <$> Ref.read files + contents <- + case cache of + Just lines -> pure lines + Nothing -> do + lines <- Str.split (Str.Pattern "\n") <$> File.readTextFile Encoding.UTF8 filename + Ref.modify_ (FO.insert filename lines) files + pure lines + let source = Array.slice (pos.startLine - 1) (pos.endLine) contents + pure $ Just source + + decodeStash s = jsonParser s >>= decodeJson >>= traverse parsePsaError + encodeStash s = encodeJson (encodePsaError <$> s) + + emptyStash :: forall a. Effect { date :: DateTime, stash :: Array a } + emptyStash = { date: _, stash: [] } <$> toDateTime <$> now + + readStashFile stashFile = catchException (const emptyStash) do + stat <- File.stat stashFile + file <- File.readTextFile Encoding.UTF8 stashFile + case decodeStash file of + Left _ -> emptyStash + Right stash -> pure { date: Stats.modifiedTime stat, stash } + + writeStashFile stashFile warnings = do + let file = stringify (encodeStash warnings) + File.writeTextFile Encoding.UTF8 stashFile file + + mergeWarnings filenames date old new = do + fileStat <- Ref.new FO.empty + old' <- flip Array.filterA old \x -> + case x.filename of + Nothing -> pure false + Just f -> + if Set.member f filenames then pure false + else do + stat <- FO.lookup f <$> Ref.read fileStat + case stat of + Just s -> pure s + Nothing -> do + s <- catchException (\_ -> pure false) $ + (date > _) <<< Stats.modifiedTime <$> File.stat f + _ <- Ref.modify_ (FO.insert f s) fileStat + pure s + pure $ old' <> new + +-- Indicates which output stream we are interested in when spawning a child process. +data OutputStream = Stdout | Stderr + +usage :: String +usage = + """psa - Error/Warning reporting frontend for 'purs compile' + +Usage: psa [--censor-lib] [--censor-src] + [--censor-codes=CODES] [--filter-codes=CODES] + [--no-colors] [--no-source] + [--is-lib=DIR] [--purs=PURS] [--stash] + PSC_OPTIONS + +Available options: + -v,--version Show the version number + -h,--help Show this help text + --verbose-stats Show counts for each warning type + --censor-stats Censor warning/error summary + --censor-warnings Censor all warnings + --censor-lib Censor warnings from library sources + --censor-src Censor warnings from project sources + --censor-codes=CODES Censor specific error codes + --filter-codes=CODES Only show specific error codes + --no-colors Disable ANSI colors + --no-source Disable original source code printing + --strict Promotes src warnings to errors + --stash Enable persistent warnings (defaults to .psa-stash) + --stash=FILE Enable persistent warnings using a specific stash file + --is-lib=DIR Distinguishing library path (defaults to 'bower_components') + --purs=PURS Name of purs executable (defaults to 'purs') + + CODES Comma-separated list of purs error codes + PSC_OPTIONS Any extra options are passed to 'purs compile' +""" diff --git a/spaghetto/src/Spago/Psa/Output.purs b/spaghetto/src/Spago/Psa/Output.purs new file mode 100644 index 000000000..f8e3030e9 --- /dev/null +++ b/spaghetto/src/Spago/Psa/Output.purs @@ -0,0 +1,274 @@ +-- A majority of this code was copied from +-- - https://github.com/natefaubion/purescript-psa-utils +-- +-- To fullfil license requirements +-- Copyright © Nathan Faubion +-- https://opensource.org/license/mit/ +module Spago.Psa.Output + ( output + , Output + , OutputStats + , annotatedError + , trimPosition + , trimMessage + ) where + +import Prelude + +import Data.Array as Array +import Data.Foldable (foldl, any) +import Data.Maybe (Maybe(..), fromMaybe) +import Data.Set as Set +import Data.String as Str +import Data.Tuple (Tuple(..)) +import Foreign.Object as FO +import Node.Path as Path +import Psa.Types (PsaOptions, PsaError, PsaAnnotedError, PsaPath(..), PsaResult, Position, Filename, Lines, compareByLocation) + +data ErrorTag = Error | Warning + +type Output = + { warnings :: Array PsaAnnotedError + , errors :: Array PsaAnnotedError + , stats :: OutputStats + } + +-- | Statistics are a ratio of errors shown to errors in total. +type OutputStats = + { allWarnings :: FO.Object (Tuple Int Int) + , allErrors :: FO.Object (Tuple Int Int) + , srcWarnings :: FO.Object (Tuple Int Int) + , srcErrors :: FO.Object (Tuple Int Int) + , libWarnings :: FO.Object (Tuple Int Int) + , libErrors :: FO.Object (Tuple Int Int) + } + +initialStats :: OutputStats +initialStats = + { allWarnings: FO.empty + , allErrors: FO.empty + , srcWarnings: FO.empty + , srcErrors: FO.empty + , libWarnings: FO.empty + , libErrors: FO.empty + } + +-- | Annotates a error/warning result set with original source lines, better +-- | positions, and semantic paths (lib vs src). The callback should load the +-- | requested set of lines from the absolute filename based on the tentative +-- | position information. +output + :: forall m + . (Monad m) + => (Filename -> Position -> m (Maybe Lines)) + -> PsaOptions + -> PsaResult + -> m Output +output loadLines options result = do + let + result' = + { warnings: pathOf <$> result.warnings + , errors: pathOf <$> result.errors + } + initialState = + { warnings: [] + , errors: [] + , stats: initialStats + } + state <- Array.foldM (onError Warning) initialState result'.warnings + state' <- Array.foldM (onError Error) state result'.errors + pure state' + { warnings = Array.sortBy compareByLocation state'.warnings + , errors = Array.sortBy compareByLocation state'.errors + } + + where + pathOf :: PsaError -> Tuple PsaPath PsaError + pathOf x = + case x.filename of + Just f | f /= "" -> + let + path + | Path.isAbsolute f = f + | otherwise = Path.concat [ options.cwd, f ] + in + Tuple (errorPath options.libDirs path f) x + _ -> Tuple Unknown x + + onError :: ErrorTag -> Output -> Tuple PsaPath PsaError -> m Output + onError tag state (Tuple path error) = + if shouldShowError options tag path error.errorCode then do + source <- fromMaybe (pure Nothing) (loadLines <$> error.filename <*> error.position) + update [ annotatedError path source error ] + else + update [] + + where + update :: Array PsaAnnotedError -> m Output + update log = + pure $ onTag + (_ { stats = stats, errors = state.errors <> log }) + (_ { stats = stats, warnings = state.warnings <> log }) + tag' + state + where + printed = not (Array.null log) + tag' = if printed && options.strict && isSrc path then Error else tag + stats = updateStats tag' path error.errorCode printed state.stats + +annotatedError :: PsaPath -> Maybe Lines -> PsaError -> PsaAnnotedError +annotatedError path lines error = { path, position, message, source, error } + where + position = trimPosition <$> lines <*> error.position + message = trimMessage error.message + source = (\p -> Array.take (p.endLine - p.startLine + 1)) <$> position <*> lines + +partition :: forall a. (a -> Boolean) -> Array a -> { pass :: Array a, fail :: Array a } +partition f = foldl go { pass: [], fail: [] } + where + go { pass, fail } x = + if f x then { pass: Array.snoc pass x, fail } + else { pass, fail: Array.snoc fail x } + +updateStats + :: ErrorTag + -> PsaPath + -> String + -> Boolean -- If the error was printed + -> OutputStats + -> OutputStats +updateStats tag path code printed s = + { allWarnings: onTag identity bumpCode tag s.allWarnings + , allErrors: onTag bumpCode identity tag s.allErrors + , srcWarnings: onTag identity (onPath bumpCode identity path) tag s.srcWarnings + , srcErrors: onTag (onPath bumpCode identity path) identity tag s.srcErrors + , libWarnings: onTag identity (onPath identity bumpCode path) tag s.libWarnings + , libErrors: onTag (onPath identity bumpCode path) identity tag s.libErrors + } + + where + bumpCode = FO.alter alterStat code + bump (Tuple a b) = Tuple (if printed then a + 1 else a) (b + 1) + alterStat Nothing = Just (bump (Tuple 0 0)) + alterStat (Just x) = Just (bump x) + +shouldShowError :: PsaOptions -> ErrorTag -> PsaPath -> String -> Boolean +shouldShowError _ Error _ _ = true +shouldShowError { filterCodes, censorCodes, censorSrc, censorLib, censorWarnings } _ path code = + not censorWarnings + && not (censorSrc && isSrc path || censorLib && isLib path) + && (Set.isEmpty filterCodes || Set.member code filterCodes) + && (Set.isEmpty censorCodes || not (Set.member code censorCodes)) + +errorPath :: Array String -> String -> String -> PsaPath +errorPath libDirs path short = + if any (\dir -> path `startsWith` Str.Pattern dir) libDirs then Lib short + else Src short + where + startsWith s' s = + case Str.indexOf s s' of + Just 0 -> true + _ -> false + +onTag :: forall a b. (a -> b) -> (a -> b) -> ErrorTag -> a -> b +onTag f g Error x = f x +onTag f g Warning x = g x + +onPath :: forall a. (a -> a) -> (a -> a) -> PsaPath -> a -> a +onPath f g (Src _) x = f x +onPath f g (Lib _) x = g x +onPath f g _ x = x + +isLib :: PsaPath -> Boolean +isLib (Lib _) = true +isLib _ = false + +isSrc :: PsaPath -> Boolean +isSrc (Src _) = true +isSrc _ = false + +isWarning :: ErrorTag -> Boolean +isWarning Warning = true +isWarning _ = false + +-- | Finds the true bounds of the source. The PureScript compiler is greedy +-- | when it comes to matching whitespace at the end of an expression, so the +-- | original source bounds always includes whitespace and comments. +trimPosition :: Lines -> Position -> Position +trimPosition lines pos = + case lines of + [] -> + { startLine: pos.startLine + , startColumn: pos.startColumn + , endLine: pos.startLine + , endColumn: pos.startColumn + } + + [ l ] -> + case trimCol (pos.endColumn) l of + Just col -> pos { endLine = pos.startLine, endColumn = col } + Nothing -> pos { endLine = pos.startLine, endColumn = pos.startColumn } + + _ -> + case trimPos { row: pos.endLine, col: pos.endColumn } of + Just { row, col } -> pos { endLine = row, endColumn = col } + Nothing -> trimPosition [] pos + + where + -- WARNING: here be off-by-one dragons! + + trimPos { row, col } + | col <= 1 = + case Array.index lines (row - pos.startLine - 1) of + Just l -> trimPos { row: row - 1, col: Str.length l + 1 } + _ -> Nothing + + | otherwise = + case Array.index lines (row - pos.startLine) of + Just l -> + case trimCol col l of + Just col' -> Just { row, col: col' } + Nothing -> trimPos { row, col: 1 } + + _ -> Nothing + + trimCol col l = + case Str.codePointAt (col - 2) l of + Just x | isPunc x -> trimCol (col - 1) l + Just _ -> trimComment col l + _ -> Nothing + + -- TODO: this breaks if "--" is inside a quoted string. + -- TODO: Block comments? + trimComment col l = + case Str.indexOf (Str.Pattern "--") l of + Just x | x == 0 -> Nothing + Just x | x < (col - 1) -> trimCol (x + 1) l + _ -> Just col + + isPunc = (_ == Str.codePointFromChar ' ') || (_ == Str.codePointFromChar ',') + +-- | Trims extraneous whitespace from psc error messages. +trimMessage :: String -> String +trimMessage = + Str.split (Str.Pattern "\n") + >>> foldl dedent { lines: [], indent: top } + >>> _.lines + >>> foldl collapse [] + >>> Str.joinWith "\n" + >>> Str.trim + + where + dedent { lines, indent } l + | l == "" = { lines: Array.snoc lines l, indent } + | otherwise = + let + indent' = Str.length $ Str.takeWhile (_ == Str.codePointFromChar ' ') l + in + if indent' < indent then { lines: Array.snoc lines (Str.drop indent' l), indent: indent' } + else { lines: Array.snoc lines (Str.drop indent l), indent } + + collapse lines l = + case Array.last lines of + Just "" | l == "" -> lines + _ -> Array.snoc lines l diff --git a/spaghetto/src/Spago/Psa/Printer.purs b/spaghetto/src/Spago/Psa/Printer.purs new file mode 100644 index 000000000..1c3b15de9 --- /dev/null +++ b/spaghetto/src/Spago/Psa/Printer.purs @@ -0,0 +1,135 @@ +-- A majority of this code was copied from +-- - https://github.com/natefaubion/purescript-psa-utils +-- +-- To fullfil license requirements +-- Copyright © Nathan Faubion +-- https://opensource.org/license/mit/ +module Spago.Psa.Printer + ( Row() + , line + , indent + , para + , AnsiText() + , plain + , style + , ansiLength + , Rendered + , render + , renderRow + , renderAnsi + , renderSource + ) where + +import Prelude +import Prim hiding (Row) + +import Ansi.Codes as Ansi +import Ansi.Output (foreground, dim) +import Data.Array as Array +import Data.List.NonEmpty (NonEmptyList) +import Data.List.NonEmpty as NEL +import Data.String as Str +import Data.Tuple (uncurry) +import Psa.Types (Position, Lines) +import Psa.Util (replicate, padLeft) + +type Rendered = Row (Array AnsiText) + +data Row a + = Line a + | Indent a (Row a) + | Para (Array (Row a)) + +line :: forall a. a -> Row a +line = Line + +indent :: forall a. a -> Row a -> Row a +indent = Indent + +para :: forall a. Array (Row a) -> Row a +para = Para + +instance semigroupRow :: Semigroup (Row a) where + append a@(Line _) b@(Para bs) = Para (Array.cons a bs) + append a@(Indent _ _) b@(Para bs) = Para (Array.cons a bs) + append a@(Para as) b@(Line _) = Para (Array.snoc as b) + append a@(Para as) b@(Indent _ _) = Para (Array.snoc as b) + append a@(Para as) b@(Para bs) = Para (as <> bs) + append a b = Para [ a, b ] + +instance monoidRow :: Monoid (Row a) where + mempty = Para [] + +data AnsiText + = Plain String + | Style (NonEmptyList Ansi.GraphicsParam) String + +plain :: String -> AnsiText +plain = Plain + +style :: NonEmptyList Ansi.GraphicsParam -> String -> AnsiText +style = Style + +ansiLength :: AnsiText -> Int +ansiLength (Plain a) = Str.length a +ansiLength (Style _ a) = Str.length a + +render :: Boolean -> Rendered -> String +render ansi = renderRow (Str.joinWith "" <<< map (renderAnsi ansi)) + +renderRow :: forall a. (a -> String) -> Row a -> String +renderRow f = go "" + where + go ind (Line a) = ind <> f a + go ind (Para as) = Str.joinWith "\n" (go ind <$> as) + go ind (Indent i as) = go (ind <> f i) as + +renderAnsi :: Boolean -> AnsiText -> String +renderAnsi false (Plain s) = s +renderAnsi false (Style _ s) = s +renderAnsi true (Plain s) = s +renderAnsi true (Style g s) = + Ansi.escapeCodeToString (Ansi.Graphics g) <> s <> Ansi.escapeCodeToString (Ansi.Graphics (NEL.singleton Ansi.Reset)) + +renderSource :: Position -> Lines -> Rendered +renderSource pos lines = renderAnnotation (gutter + 2) pos source' + where + lineNums = Array.range pos.startLine pos.endLine + gutter = Str.length (show pos.endLine) + source = uncurry (sourceLine gutter " ") <$> Array.zip lineNums lines + source' = + if Array.length source > 7 then Array.take 3 source + <> [ [ plain $ replicate (gutter + 2) " ", style dim "..." ] ] + <> Array.drop (Array.length source - 3) source + else source + +renderAnnotation :: Int -> Position -> Array (Array AnsiText) -> Rendered +renderAnnotation offset pos lines = para + case lines of + [ l ] -> + [ line l + , line $ renderErrorRange (pos.startColumn + offset) (pos.endColumn - pos.startColumn) + ] + _ -> + [ line $ renderErrorTick (pos.startColumn + offset) "v" + , para (line <$> lines) + , line $ renderErrorTick (pos.endColumn + offset - 1) "^" + ] + +sourceLine :: Int -> String -> Int -> String -> Array AnsiText +sourceLine gutter sep num code = + [ style dim $ padLeft gutter (show num) <> sep + , plain code + ] + +renderErrorRange :: Int -> Int -> Array AnsiText +renderErrorRange start len = + [ plain $ replicate (start - 1) " " + , style (foreground Ansi.Red) $ replicate len "^" + ] + +renderErrorTick :: Int -> String -> Array AnsiText +renderErrorTick start char = + [ plain $ replicate (start - 1) " " + , style (foreground Ansi.Red) char + ] diff --git a/spaghetto/src/Spago/Psa/Printer/Default.purs b/spaghetto/src/Spago/Psa/Printer/Default.purs new file mode 100644 index 000000000..bf9d31fc6 --- /dev/null +++ b/spaghetto/src/Spago/Psa/Printer/Default.purs @@ -0,0 +1,186 @@ +-- A majority of this code was copied from +-- - https://github.com/natefaubion/purescript-psa-utils +-- +-- To fullfil license requirements +-- Copyright © Nathan Faubion +-- https://opensource.org/license/mit/ +module Spago.Psa.Printer.Default + ( renderWarning + , renderError + , renderStats + , renderVerboseStats + , print + ) where + +import Prelude + +import Ansi.Codes as Ansi +import Ansi.Output (foreground, dim) +import Data.Array as Array +import Data.Foldable (sum, maximum) +import Data.List.NonEmpty (NonEmptyList) +import Data.Maybe (Maybe(..), fromMaybe) +import Data.String as Str +import Data.Tuple (Tuple(..)) +import Effect (Effect) +import Effect.Console as Console +import Foreign.Object as FO +import Psa.Output (OutputStats, Output) +import Psa.Printer (Rendered, AnsiText, ansiLength, renderSource, plain, style, indent, line, para, render) +import Psa.Types (Lines, Position, PsaAnnotedError, PsaOptions, PsaPath(..), StatVerbosity(..)) +import Psa.Util (replicate, iter_) + +-- | Prints output to the console. +print :: PsaOptions -> Output -> Effect Unit +print options output = do + iter_ output.warnings \i warning -> do + Console.error $ toString (renderWarning lenWarnings (i + 1) warning) + Console.error "" + + iter_ output.errors \i error -> do + Console.error $ toString (renderError lenErrors (i + 1) error) + Console.error "" + + Console.error $ toString (renderStats' output.stats) + + where + toString = render options.ansi + lenWarnings = Array.length output.warnings + lenErrors = Array.length output.errors + renderStats' = case options.statVerbosity of + NoStats -> mempty + CompactStats -> renderStats + VerboseStats -> renderVerboseStats + +renderWarning :: Int -> Int -> PsaAnnotedError -> Rendered +renderWarning = renderWrapper (foreground Ansi.Yellow) + +renderError :: Int -> Int -> PsaAnnotedError -> Rendered +renderError = renderWrapper (foreground Ansi.Red) + +renderWrapper :: NonEmptyList Ansi.GraphicsParam -> Int -> Int -> PsaAnnotedError -> Rendered +renderWrapper gfx total index { error, path, position, source, message } = + para + [ line $ + [ renderStatus gfx total index error.errorCode + , plain " " + , renderPath path error.moduleName + ] <> fromMaybe mempty (renderPosition <$> position) + , emptyLine + , indented + $ fromMaybe mempty (renderSource' <$> position <*> source) + <> toLines message + ] + +toLines :: String -> Rendered +toLines = para <<< map (line <<< Array.singleton <<< plain) <<< Str.split (Str.Pattern "\n") + +emptyLine :: Rendered +emptyLine = line [ plain "" ] + +indented :: Rendered -> Rendered +indented = indent [ plain " " ] + +renderStatus :: NonEmptyList Ansi.GraphicsParam -> Int -> Int -> String -> AnsiText +renderStatus gfx total index code = + style gfx $ "[" <> show index <> "/" <> show total <> " " <> code <> "]" + +renderModuleName :: Maybe String -> AnsiText +renderModuleName Nothing = style dim "(unknown module)" +renderModuleName (Just m) = plain m + +renderPath :: PsaPath -> Maybe String -> AnsiText +renderPath (Src f) _ = plain f +renderPath (Lib f) _ = plain f +renderPath _ m = renderModuleName m + +renderPosition :: Position -> Array AnsiText +renderPosition pos = + [ style dim ":" + , plain (show pos.startLine) + , style dim ":" + , plain (show pos.startColumn) + ] + +renderSource' :: Position -> Lines -> Rendered +renderSource' pos lines = renderSource pos lines <> emptyLine + +renderStats :: OutputStats -> Rendered +renderStats stats = + renderStatCols + [ [ style (foreground Ansi.Yellow) "Warnings" ] + , [ style (foreground Ansi.Red) "Errors" ] + ] + [ renderStat srcWarnings + , renderStat srcErrors + ] + [ renderStat libWarnings + , renderStat libErrors + ] + [ renderStat allWarnings + , renderStat allErrors + ] + where + sumRatio (Tuple a b) _ (Tuple c d) = Tuple (a + c) (b + d) + srcWarnings = FO.fold sumRatio (Tuple 0 0) stats.srcWarnings + srcErrors = FO.fold sumRatio (Tuple 0 0) stats.srcErrors + libWarnings = FO.fold sumRatio (Tuple 0 0) stats.libWarnings + libErrors = FO.fold sumRatio (Tuple 0 0) stats.libErrors + allWarnings = FO.fold sumRatio (Tuple 0 0) stats.allWarnings + allErrors = FO.fold sumRatio (Tuple 0 0) stats.allErrors + +renderVerboseStats :: OutputStats -> Rendered +renderVerboseStats stats = + renderStatCols + (warningLabels <> errorLabels) + (srcWarnings <> srcErrors) + (libWarnings <> libErrors) + (allWarnings <> allErrors) + where + warnings = Array.sort (FO.keys stats.allWarnings) + errors = Array.sort (FO.keys stats.allErrors) + + warningLabels = Array.singleton <<< style (foreground Ansi.Yellow) <$> warnings + errorLabels = Array.singleton <<< style (foreground Ansi.Red) <$> errors + + getStat key x = fromMaybe (Tuple 0 0) $ FO.lookup key x + getStats ks x = (\k -> renderStat $ getStat k x) <$> ks + + srcWarnings = getStats warnings stats.srcWarnings + srcErrors = getStats errors stats.srcErrors + libWarnings = getStats warnings stats.libWarnings + libErrors = getStats errors stats.libErrors + allWarnings = getStats warnings stats.allWarnings + allErrors = getStats errors stats.allErrors + +renderStatCols :: Array (Array AnsiText) -> Array (Array AnsiText) -> Array (Array AnsiText) -> Array (Array AnsiText) -> Rendered +renderStatCols col1 col2 col3 col4 = para $ + catRow + `map` alignLeft ([ [ plain "" ] ] <> col1) + `Array.zipWith ($)` + alignLeft ([ [ plain "Src" ] ] <> col2) + `Array.zipWith ($)` + alignLeft ([ [ plain "Lib" ] ] <> col3) + `Array.zipWith ($)` + alignLeft ([ [ plain "All" ] ] <> col4) + + where + gutter = [ plain " " ] + catRow c1 c2 c3 c4 = + line $ c1 <> gutter <> c2 <> gutter <> c3 <> gutter <> c4 + + lineLength = sum <<< map ansiLength + alignRight = align \a as -> Array.cons a as + alignLeft = align \a as -> Array.snoc as a + align f ls = map pad ls + where + max = fromMaybe 0 $ maximum (map lineLength ls) + pad l = f (plain $ replicate (max - lineLength l) " ") l + +renderStat :: Tuple Int Int -> Array AnsiText +renderStat (Tuple 0 0) = [ style (foreground Ansi.Green) "0" ] +renderStat (Tuple a b) | a == b = [ plain $ show a ] +renderStat (Tuple a b) = + [ plain $ show a + , style dim $ "/" <> show b + ] diff --git a/spaghetto/src/Spago/Psa/Printer/Json.purs b/spaghetto/src/Spago/Psa/Printer/Json.purs new file mode 100644 index 000000000..12e503ac3 --- /dev/null +++ b/spaghetto/src/Spago/Psa/Printer/Json.purs @@ -0,0 +1,21 @@ +module Spago.Psa.Printer.Json + ( print + ) where + +import Prelude + +import Data.Argonaut.Core (stringify) +import Effect (Effect) +import Effect.Console as Console +import Psa.Output (Output) +import Psa.Types (encodePsaResult) + +print :: Output -> Effect Unit +print output = do + let + result = encodePsaResult + { warnings: _.error <$> output.warnings + , errors: _.error <$> output.errors + } + + Console.error (stringify result) diff --git a/spaghetto/src/Spago/Psa/Types.purs b/spaghetto/src/Spago/Psa/Types.purs new file mode 100644 index 000000000..416bf9460 --- /dev/null +++ b/spaghetto/src/Spago/Psa/Types.purs @@ -0,0 +1,217 @@ +-- A majority of this code was copied from +-- - https://github.com/natefaubion/purescript-psa-utils +-- +-- To fullfil license requirements +-- Copyright © Nathan Faubion +-- https://opensource.org/license/mit/ +module Spago.Psa.Types + ( ErrorCode + , ModuleName + , Filename + , StatVerbosity(..) + , PsaOptions + , PsaResult + , PsaError + , PsaAnnotedError + , PsaPath(..) + , Position + , Suggestion + , Lines + , parsePsaResult + , parsePsaError + , encodePsaResult + , encodePsaError + , compareByLocation + ) where + +import Prelude + +import Data.Argonaut.Core (Json, jsonNull) +import Data.Argonaut.Decode (class DecodeJson, decodeJson, printJsonDecodeError) +import Data.Argonaut.Decode.Combinators as Decode.Combinators +import Data.Argonaut.Encode (encodeJson) +import Data.Bifunctor (lmap) +import Data.Either (Either(..)) +import Data.Maybe (Maybe(..), maybe) +import Data.Set (Set) +import Data.Traversable (traverse) +import Data.Tuple (Tuple(..)) +import Foreign.Object as FO +import Foreign.Object.ST as FOST +import Unsafe.Coerce (unsafeCoerce) + +type ErrorCode = String +type ModuleName = String +type Filename = String +type Lines = Array String + +data StatVerbosity = NoStats | CompactStats | VerboseStats + +-- | Relative files paths from the cwd, tagged as either being part of the +-- | source files or library files of a project. The `Unknown` variant exists +-- | because some psc errors are inter-module and aren't reported with a +-- | canonical file. +data PsaPath + = Src String + | Lib String + | Unknown + +instance eqPsaPath :: Eq PsaPath where + eq (Src a) (Src b) = eq a b + eq (Lib a) (Lib b) = eq a b + eq Unknown Unknown = true + eq _ _ = false + +instance ordPsaPath :: Ord PsaPath where + compare (Src a) (Src b) = compare a b + compare (Src _) (Lib _) = GT + compare (Src _) Unknown = GT + compare (Lib _) (Src _) = LT + compare (Lib a) (Lib b) = compare a b + compare (Lib _) Unknown = GT + compare Unknown Unknown = EQ + compare Unknown _ = LT + +type PsaOptions = + { ansi :: Boolean + , censorWarnings :: Boolean + , censorLib :: Boolean + , censorSrc :: Boolean + , censorCodes :: Set ErrorCode + , filterCodes :: Set ErrorCode + , statVerbosity :: StatVerbosity + , libDirs :: Array String + , strict :: Boolean + , cwd :: String + } + +type PsaResult = + { warnings :: Array PsaError + , errors :: Array PsaError + } + +type PsaError = + { moduleName :: Maybe ModuleName + , errorCode :: ErrorCode + , errorLink :: String + , suggestion :: Maybe Suggestion + , message :: String + , filename :: Maybe Filename + , position :: Maybe Position + } + +type PsaAnnotedError = + { error :: PsaError + , path :: PsaPath + , source :: Maybe Lines + , position :: Maybe Position + , message :: String + } + +type Position = + { startLine :: Int + , startColumn :: Int + , endLine :: Int + , endColumn :: Int + } + +type Suggestion = + { replacement :: String + , replaceRange :: Maybe Position + } + +compareByLocation :: PsaAnnotedError -> PsaAnnotedError -> Ordering +compareByLocation err1 err2 = + case compare err1.path err2.path of + EQ -> + case err1.position, err2.position of + Nothing, Nothing -> EQ + Nothing, _ -> LT + _, Nothing -> GT + Just a, Just b -> + compare (Tuple a.startLine a.startColumn) + (Tuple b.startLine b.startColumn) + x -> x + +parsePsaResult :: FO.Object Json -> Either String PsaResult +parsePsaResult obj = + { warnings: _ + , errors: _ + } <$> (obj .: "warnings" >>= traverse parsePsaError) + <*> (obj .: "errors" >>= traverse parsePsaError) + +parsePsaError :: FO.Object Json -> Either String PsaError +parsePsaError obj = + { moduleName: _ + , errorCode: _ + , errorLink: _ + , message: _ + , filename: _ + , position: _ + , suggestion: _ + } <$> obj .: "moduleName" + <*> obj .: "errorCode" + <*> obj .: "errorLink" + <*> obj .: "message" + <*> obj .: "filename" + <*> (obj .: "position" >>= parsePosition) + <*> (obj .: "suggestion" >>= parseSuggestion) + +parsePosition :: Maybe (FO.Object Json) -> Either String (Maybe Position) +parsePosition = + maybe (pure Nothing) \obj -> map Just $ + { startLine: _ + , startColumn: _ + , endLine: _ + , endColumn: _ + } <$> obj .: "startLine" + <*> obj .: "startColumn" + <*> obj .: "endLine" + <*> obj .: "endColumn" + +parseSuggestion :: Maybe (FO.Object Json) -> Either String (Maybe Suggestion) +parseSuggestion = + maybe (pure Nothing) \obj -> map Just $ + { replacement: _ + , replaceRange: _ + } <$> obj .: "replacement" + <*> (obj .:? "replaceRange" >>= parsePosition) + +encodePsaResult :: PsaResult -> Json +encodePsaResult res = encodeJson $ FO.runST do + obj <- FOST.new + _ <- FOST.poke "warnings" (encodeJson (encodePsaError <$> res.warnings)) obj + _ <- FOST.poke "errors" (encodeJson (encodePsaError <$> res.errors)) obj + pure obj + +encodePsaError :: PsaError -> Json +encodePsaError error = encodeJson $ FO.runST do + obj <- FOST.new + _ <- FOST.poke "moduleName" (encodeJson error.moduleName) obj + _ <- FOST.poke "errorCode" (encodeJson error.errorCode) obj + _ <- FOST.poke "errorLink" (encodeJson error.errorLink) obj + _ <- FOST.poke "message" (encodeJson error.message) obj + _ <- FOST.poke "filename" (encodeJson error.filename) obj + _ <- FOST.poke "position" (encodeJson (maybe jsonNull encodePosition error.position)) obj + _ <- FOST.poke "suggestion" (encodeJson (maybe jsonNull encodeSuggestion error.suggestion)) obj + pure obj + +encodePosition :: Position -> Json +encodePosition = unsafeCoerce + +encodeSuggestion :: Suggestion -> Json +encodeSuggestion suggestion = encodeJson $ FO.runST do + obj <- FOST.new + _ <- FOST.poke "replacement" (encodeJson suggestion.replacement) obj + _ <- FOST.poke "replaceRange" (encodeJson (maybe jsonNull encodePosition suggestion.replaceRange)) obj + pure obj + +maybeProp :: forall a. (DecodeJson a) => FO.Object Json -> String -> Either String (Maybe a) +maybeProp obj key = maybe (Right Nothing) (lmap printJsonDecodeError <<< decodeJson) (FO.lookup key obj) + +infix 7 maybeProp as .:? + +getField :: forall a. (DecodeJson a) => FO.Object Json -> String -> Either String a +getField obj key = lmap printJsonDecodeError (Decode.Combinators.getField obj key) + +infix 7 getField as .: diff --git a/spaghetto/src/Spago/Psa/Util.purs b/spaghetto/src/Spago/Psa/Util.purs new file mode 100644 index 000000000..3ffced070 --- /dev/null +++ b/spaghetto/src/Spago/Psa/Util.purs @@ -0,0 +1,30 @@ +-- A majority of this code was copied from +-- - https://github.com/natefaubion/purescript-psa-utils +-- +-- To fullfil license requirements +-- Copyright © Nathan Faubion +-- https://opensource.org/license/mit/ +module Spago.Psa.Util where + +import Prelude +import Data.Foldable (class Foldable, foldl) +import Data.String as Str +import Data.Tuple (Tuple(..), snd) + +replicate :: forall m. (Monoid m) => Int -> m -> m +replicate n m = go n mempty + where + go i x + | i <= 0 = x + | otherwise = go (i - 1) (x <> m) + +padLeft :: Int -> String -> String +padLeft width str = replicate (width - Str.length str) " " <> str + +padRight :: Int -> String -> String +padRight width str = str <> replicate (width - Str.length str) " " + +iter_ :: forall m f a b. Foldable f => Applicative m => f a -> (Int -> a -> m b) -> m Unit +iter_ xs f = snd $ foldl go (Tuple 0 (pure unit)) xs + where + go (Tuple i a) b = Tuple (i + 1) (a <* f i b) From 64c9b45da0837762dd91a4a014ca0a0796b8a47b Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 30 Mar 2023 01:59:17 -0500 Subject: [PATCH 02/78] Update imports to Spago-based ones --- spaghetto/src/Spago/Psa.purs | 6 +++--- spaghetto/src/Spago/Psa/Output.purs | 2 +- spaghetto/src/Spago/Psa/Printer.purs | 4 ++-- spaghetto/src/Spago/Psa/Printer/Default.purs | 8 ++++---- spaghetto/src/Spago/Psa/Printer/Json.purs | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index 84b4859fa..e83a42edf 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -38,9 +38,9 @@ import Node.Platform (Platform(Win32)) import Node.Process as Process import Node.Stream as Stream import Partial.Unsafe (unsafePartial) -import Psa (PsaOptions, StatVerbosity(..), parsePsaResult, parsePsaError, encodePsaError, output) -import Psa.Printer.Default as DefaultPrinter -import Psa.Printer.Json as JsonPrinter +import Spago.Psa (PsaOptions, StatVerbosity(..), parsePsaResult, parsePsaError, encodePsaError, output) +import Spago.Psa.Printer.Default as DefaultPrinter +import Spago.Psa.Printer.Json as JsonPrinter foreign import version :: String diff --git a/spaghetto/src/Spago/Psa/Output.purs b/spaghetto/src/Spago/Psa/Output.purs index f8e3030e9..17a20e2db 100644 --- a/spaghetto/src/Spago/Psa/Output.purs +++ b/spaghetto/src/Spago/Psa/Output.purs @@ -23,7 +23,7 @@ import Data.String as Str import Data.Tuple (Tuple(..)) import Foreign.Object as FO import Node.Path as Path -import Psa.Types (PsaOptions, PsaError, PsaAnnotedError, PsaPath(..), PsaResult, Position, Filename, Lines, compareByLocation) +import Spago.Psa.Types (PsaOptions, PsaError, PsaAnnotedError, PsaPath(..), PsaResult, Position, Filename, Lines, compareByLocation) data ErrorTag = Error | Warning diff --git a/spaghetto/src/Spago/Psa/Printer.purs b/spaghetto/src/Spago/Psa/Printer.purs index 1c3b15de9..898fa0197 100644 --- a/spaghetto/src/Spago/Psa/Printer.purs +++ b/spaghetto/src/Spago/Psa/Printer.purs @@ -30,8 +30,8 @@ import Data.List.NonEmpty (NonEmptyList) import Data.List.NonEmpty as NEL import Data.String as Str import Data.Tuple (uncurry) -import Psa.Types (Position, Lines) -import Psa.Util (replicate, padLeft) +import Spago.Psa.Types (Position, Lines) +import Spago.Psa.Util (replicate, padLeft) type Rendered = Row (Array AnsiText) diff --git a/spaghetto/src/Spago/Psa/Printer/Default.purs b/spaghetto/src/Spago/Psa/Printer/Default.purs index bf9d31fc6..2dbd42d04 100644 --- a/spaghetto/src/Spago/Psa/Printer/Default.purs +++ b/spaghetto/src/Spago/Psa/Printer/Default.purs @@ -25,10 +25,10 @@ import Data.Tuple (Tuple(..)) import Effect (Effect) import Effect.Console as Console import Foreign.Object as FO -import Psa.Output (OutputStats, Output) -import Psa.Printer (Rendered, AnsiText, ansiLength, renderSource, plain, style, indent, line, para, render) -import Psa.Types (Lines, Position, PsaAnnotedError, PsaOptions, PsaPath(..), StatVerbosity(..)) -import Psa.Util (replicate, iter_) +import Spago.Psa.Output (OutputStats, Output) +import Spago.Psa.Printer (Rendered, AnsiText, ansiLength, renderSource, plain, style, indent, line, para, render) +import Spago.Psa.Types (Lines, Position, PsaAnnotedError, PsaOptions, PsaPath(..), StatVerbosity(..)) +import Spago.Psa.Util (replicate, iter_) -- | Prints output to the console. print :: PsaOptions -> Output -> Effect Unit diff --git a/spaghetto/src/Spago/Psa/Printer/Json.purs b/spaghetto/src/Spago/Psa/Printer/Json.purs index 12e503ac3..94088a874 100644 --- a/spaghetto/src/Spago/Psa/Printer/Json.purs +++ b/spaghetto/src/Spago/Psa/Printer/Json.purs @@ -7,8 +7,8 @@ import Prelude import Data.Argonaut.Core (stringify) import Effect (Effect) import Effect.Console as Console -import Psa.Output (Output) -import Psa.Types (encodePsaResult) +import Spago.Psa.Output (Output) +import Spago.Psa.Types (encodePsaResult) print :: Output -> Effect Unit print output = do From 63c6dd59f36dcfb56e9741b57ba28e3f0d94e3ef Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 30 Mar 2023 02:00:34 -0500 Subject: [PATCH 03/78] Derive instances --- spaghetto/src/Spago/Psa/Types.purs | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/spaghetto/src/Spago/Psa/Types.purs b/spaghetto/src/Spago/Psa/Types.purs index 416bf9460..50d1aab5f 100644 --- a/spaghetto/src/Spago/Psa/Types.purs +++ b/spaghetto/src/Spago/Psa/Types.purs @@ -52,25 +52,13 @@ data StatVerbosity = NoStats | CompactStats | VerboseStats -- | because some psc errors are inter-module and aren't reported with a -- | canonical file. data PsaPath - = Src String + = Unknown | Lib String - | Unknown - -instance eqPsaPath :: Eq PsaPath where - eq (Src a) (Src b) = eq a b - eq (Lib a) (Lib b) = eq a b - eq Unknown Unknown = true - eq _ _ = false - -instance ordPsaPath :: Ord PsaPath where - compare (Src a) (Src b) = compare a b - compare (Src _) (Lib _) = GT - compare (Src _) Unknown = GT - compare (Lib _) (Src _) = LT - compare (Lib a) (Lib b) = compare a b - compare (Lib _) Unknown = GT - compare Unknown Unknown = EQ - compare Unknown _ = LT + | Src String + +derive instance Eq PsaPath + +derive instance Ord PsaPath type PsaOptions = { ansi :: Boolean From a5e01663fd6eb6776cdcfd57fbc3636055da3adf Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 30 Mar 2023 02:02:34 -0500 Subject: [PATCH 04/78] Relocate encoder: PsaResult --- spaghetto/src/Spago/Psa/Types.purs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/spaghetto/src/Spago/Psa/Types.purs b/spaghetto/src/Spago/Psa/Types.purs index 50d1aab5f..dcefe765a 100644 --- a/spaghetto/src/Spago/Psa/Types.purs +++ b/spaghetto/src/Spago/Psa/Types.purs @@ -128,6 +128,13 @@ parsePsaResult obj = } <$> (obj .: "warnings" >>= traverse parsePsaError) <*> (obj .: "errors" >>= traverse parsePsaError) +encodePsaResult :: PsaResult -> Json +encodePsaResult res = encodeJson $ FO.runST do + obj <- FOST.new + _ <- FOST.poke "warnings" (encodeJson (encodePsaError <$> res.warnings)) obj + _ <- FOST.poke "errors" (encodeJson (encodePsaError <$> res.errors)) obj + pure obj + parsePsaError :: FO.Object Json -> Either String PsaError parsePsaError obj = { moduleName: _ @@ -165,13 +172,6 @@ parseSuggestion = } <$> obj .: "replacement" <*> (obj .:? "replaceRange" >>= parsePosition) -encodePsaResult :: PsaResult -> Json -encodePsaResult res = encodeJson $ FO.runST do - obj <- FOST.new - _ <- FOST.poke "warnings" (encodeJson (encodePsaError <$> res.warnings)) obj - _ <- FOST.poke "errors" (encodeJson (encodePsaError <$> res.errors)) obj - pure obj - encodePsaError :: PsaError -> Json encodePsaError error = encodeJson $ FO.runST do obj <- FOST.new From 3905b178f6d68ea2bc1282dfce6cc145ef57044d Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 30 Mar 2023 02:03:05 -0500 Subject: [PATCH 05/78] Relocate encoder: PsaError --- spaghetto/src/Spago/Psa/Types.purs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/spaghetto/src/Spago/Psa/Types.purs b/spaghetto/src/Spago/Psa/Types.purs index dcefe765a..ce682e370 100644 --- a/spaghetto/src/Spago/Psa/Types.purs +++ b/spaghetto/src/Spago/Psa/Types.purs @@ -152,6 +152,18 @@ parsePsaError obj = <*> (obj .: "position" >>= parsePosition) <*> (obj .: "suggestion" >>= parseSuggestion) +encodePsaError :: PsaError -> Json +encodePsaError error = encodeJson $ FO.runST do + obj <- FOST.new + _ <- FOST.poke "moduleName" (encodeJson error.moduleName) obj + _ <- FOST.poke "errorCode" (encodeJson error.errorCode) obj + _ <- FOST.poke "errorLink" (encodeJson error.errorLink) obj + _ <- FOST.poke "message" (encodeJson error.message) obj + _ <- FOST.poke "filename" (encodeJson error.filename) obj + _ <- FOST.poke "position" (encodeJson (maybe jsonNull encodePosition error.position)) obj + _ <- FOST.poke "suggestion" (encodeJson (maybe jsonNull encodeSuggestion error.suggestion)) obj + pure obj + parsePosition :: Maybe (FO.Object Json) -> Either String (Maybe Position) parsePosition = maybe (pure Nothing) \obj -> map Just $ @@ -172,18 +184,6 @@ parseSuggestion = } <$> obj .: "replacement" <*> (obj .:? "replaceRange" >>= parsePosition) -encodePsaError :: PsaError -> Json -encodePsaError error = encodeJson $ FO.runST do - obj <- FOST.new - _ <- FOST.poke "moduleName" (encodeJson error.moduleName) obj - _ <- FOST.poke "errorCode" (encodeJson error.errorCode) obj - _ <- FOST.poke "errorLink" (encodeJson error.errorLink) obj - _ <- FOST.poke "message" (encodeJson error.message) obj - _ <- FOST.poke "filename" (encodeJson error.filename) obj - _ <- FOST.poke "position" (encodeJson (maybe jsonNull encodePosition error.position)) obj - _ <- FOST.poke "suggestion" (encodeJson (maybe jsonNull encodeSuggestion error.suggestion)) obj - pure obj - encodePosition :: Position -> Json encodePosition = unsafeCoerce From 2e656fd62d3b07258dfc210b11bb32a53259c561 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 30 Mar 2023 02:03:25 -0500 Subject: [PATCH 06/78] Relocate encoder: Position --- spaghetto/src/Spago/Psa/Types.purs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spaghetto/src/Spago/Psa/Types.purs b/spaghetto/src/Spago/Psa/Types.purs index ce682e370..d084223e4 100644 --- a/spaghetto/src/Spago/Psa/Types.purs +++ b/spaghetto/src/Spago/Psa/Types.purs @@ -176,6 +176,9 @@ parsePosition = <*> obj .: "endLine" <*> obj .: "endColumn" +encodePosition :: Position -> Json +encodePosition = unsafeCoerce + parseSuggestion :: Maybe (FO.Object Json) -> Either String (Maybe Suggestion) parseSuggestion = maybe (pure Nothing) \obj -> map Just $ @@ -184,9 +187,6 @@ parseSuggestion = } <$> obj .: "replacement" <*> (obj .:? "replaceRange" >>= parsePosition) -encodePosition :: Position -> Json -encodePosition = unsafeCoerce - encodeSuggestion :: Suggestion -> Json encodeSuggestion suggestion = encodeJson $ FO.runST do obj <- FOST.new From e077c1b0fb6e15bcb0654952ec121663d67db30a Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 30 Mar 2023 02:26:35 -0500 Subject: [PATCH 07/78] Drop unneed FFI for version --- spaghetto/src/Spago/Psa.purs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index e83a42edf..450fba818 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -42,8 +42,6 @@ import Spago.Psa (PsaOptions, StatVerbosity(..), parsePsaResult, parsePsaError, import Spago.Psa.Printer.Default as DefaultPrinter import Spago.Psa.Printer.Json as JsonPrinter -foreign import version :: String - defaultOptions :: PsaOptions defaultOptions = { ansi: true @@ -86,9 +84,6 @@ parseOptions opts args = args where parse p arg - | arg == "--version" || arg == "-v" = - Console.log version *> Process.exit 0 - | arg == "--help" || arg == "-h" = Console.log usage *> Process.exit 0 @@ -327,7 +322,6 @@ Usage: psa [--censor-lib] [--censor-src] PSC_OPTIONS Available options: - -v,--version Show the version number -h,--help Show this help text --verbose-stats Show counts for each warning type --censor-stats Censor warning/error summary From 64560237a8c3f5fb9dccbc4077bac3a6398c8837 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 30 Mar 2023 02:27:24 -0500 Subject: [PATCH 08/78] Convert class-based codecs to value-based ones --- spaghetto/spago.yaml | 1 + spaghetto/src/Spago/Psa.purs | 13 ++- spaghetto/src/Spago/Psa/Printer/Json.purs | 5 +- spaghetto/src/Spago/Psa/Types.purs | 127 +++++++--------------- 4 files changed, 48 insertions(+), 98 deletions(-) diff --git a/spaghetto/spago.yaml b/spaghetto/spago.yaml index 67743b228..8280142d7 100644 --- a/spaghetto/spago.yaml +++ b/spaghetto/spago.yaml @@ -45,6 +45,7 @@ package: - transformers - tuples - unsafe-coerce + - versions workspace: package_set: # url: https://raw.githubusercontent.com/purescript/package-sets/psc-0.15.7-20230207/packages.json diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index 450fba818..ec4bc68f7 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -9,10 +9,10 @@ module Spago.Psa where import Prelude import Data.Argonaut.Core (stringify) -import Data.Argonaut.Decode (decodeJson) -import Data.Argonaut.Encode (encodeJson) import Data.Argonaut.Parser (jsonParser) import Data.Array as Array +import Data.Bifunctor (lmap) +import Data.Codec.Argonaut as CA import Data.DateTime (DateTime) import Data.DateTime.Instant (toDateTime) import Data.Either (Either(..)) @@ -38,7 +38,8 @@ import Node.Platform (Platform(Win32)) import Node.Process as Process import Node.Stream as Stream import Partial.Unsafe (unsafePartial) -import Spago.Psa (PsaOptions, StatVerbosity(..), parsePsaResult, parsePsaError, encodePsaError, output) +import Spago.Psa.Types (PsaOptions, StatVerbosity(..), psaResultCodec, psaErrorCodec) +import Spago.Psa.Output (output) import Spago.Psa.Printer.Default as DefaultPrinter import Spago.Psa.Printer.Json as JsonPrinter @@ -180,7 +181,7 @@ main = void do else Stderr spawn' outputStream purs args \pursResult -> do for_ (Str.split (Str.Pattern "\n") pursResult.output) \err -> - case jsonParser err >>= decodeJson >>= parsePsaResult of + case jsonParser err >>= CA.decode psaResultCodec >>> lmap CA.printJsonDecodeError of Left _ -> Console.error err Right out -> do files <- Ref.new FO.empty @@ -273,8 +274,8 @@ main = void do let source = Array.slice (pos.startLine - 1) (pos.endLine) contents pure $ Just source - decodeStash s = jsonParser s >>= decodeJson >>= traverse parsePsaError - encodeStash s = encodeJson (encodePsaError <$> s) + decodeStash s = jsonParser s >>= CA.decode (CA.array psaErrorCodec) >>> lmap CA.printJsonDecodeError + encodeStash s = CA.encode (CA.array psaErrorCodec) s emptyStash :: forall a. Effect { date :: DateTime, stash :: Array a } emptyStash = { date: _, stash: [] } <$> toDateTime <$> now diff --git a/spaghetto/src/Spago/Psa/Printer/Json.purs b/spaghetto/src/Spago/Psa/Printer/Json.purs index 94088a874..ba2c054a3 100644 --- a/spaghetto/src/Spago/Psa/Printer/Json.purs +++ b/spaghetto/src/Spago/Psa/Printer/Json.purs @@ -5,15 +5,16 @@ module Spago.Psa.Printer.Json import Prelude import Data.Argonaut.Core (stringify) +import Data.Codec.Argonaut as CA import Effect (Effect) import Effect.Console as Console import Spago.Psa.Output (Output) -import Spago.Psa.Types (encodePsaResult) +import Spago.Psa.Types (psaResultCodec) print :: Output -> Effect Unit print output = do let - result = encodePsaResult + result = CA.encode psaResultCodec { warnings: _.error <$> output.warnings , errors: _.error <$> output.errors } diff --git a/spaghetto/src/Spago/Psa/Types.purs b/spaghetto/src/Spago/Psa/Types.purs index d084223e4..80360b8ae 100644 --- a/spaghetto/src/Spago/Psa/Types.purs +++ b/spaghetto/src/Spago/Psa/Types.purs @@ -17,19 +17,18 @@ module Spago.Psa.Types , Position , Suggestion , Lines - , parsePsaResult - , parsePsaError - , encodePsaResult - , encodePsaError + , psaResultCodec + , psaErrorCodec , compareByLocation ) where import Prelude -import Data.Argonaut.Core (Json, jsonNull) -import Data.Argonaut.Decode (class DecodeJson, decodeJson, printJsonDecodeError) -import Data.Argonaut.Decode.Combinators as Decode.Combinators -import Data.Argonaut.Encode (encodeJson) +import Data.Argonaut.Core (Json) +import Data.Codec.Argonaut.Record as CAR +import Data.Codec.Argonaut as CA +import Data.Codec.Argonaut.Common as CAC +import Data.Codec.Argonaut.Compat as CACompat import Data.Bifunctor (lmap) import Data.Either (Either(..)) import Data.Maybe (Maybe(..), maybe) @@ -121,85 +120,33 @@ compareByLocation err1 err2 = (Tuple b.startLine b.startColumn) x -> x -parsePsaResult :: FO.Object Json -> Either String PsaResult -parsePsaResult obj = - { warnings: _ - , errors: _ - } <$> (obj .: "warnings" >>= traverse parsePsaError) - <*> (obj .: "errors" >>= traverse parsePsaError) - -encodePsaResult :: PsaResult -> Json -encodePsaResult res = encodeJson $ FO.runST do - obj <- FOST.new - _ <- FOST.poke "warnings" (encodeJson (encodePsaError <$> res.warnings)) obj - _ <- FOST.poke "errors" (encodeJson (encodePsaError <$> res.errors)) obj - pure obj - -parsePsaError :: FO.Object Json -> Either String PsaError -parsePsaError obj = - { moduleName: _ - , errorCode: _ - , errorLink: _ - , message: _ - , filename: _ - , position: _ - , suggestion: _ - } <$> obj .: "moduleName" - <*> obj .: "errorCode" - <*> obj .: "errorLink" - <*> obj .: "message" - <*> obj .: "filename" - <*> (obj .: "position" >>= parsePosition) - <*> (obj .: "suggestion" >>= parseSuggestion) - -encodePsaError :: PsaError -> Json -encodePsaError error = encodeJson $ FO.runST do - obj <- FOST.new - _ <- FOST.poke "moduleName" (encodeJson error.moduleName) obj - _ <- FOST.poke "errorCode" (encodeJson error.errorCode) obj - _ <- FOST.poke "errorLink" (encodeJson error.errorLink) obj - _ <- FOST.poke "message" (encodeJson error.message) obj - _ <- FOST.poke "filename" (encodeJson error.filename) obj - _ <- FOST.poke "position" (encodeJson (maybe jsonNull encodePosition error.position)) obj - _ <- FOST.poke "suggestion" (encodeJson (maybe jsonNull encodeSuggestion error.suggestion)) obj - pure obj - -parsePosition :: Maybe (FO.Object Json) -> Either String (Maybe Position) -parsePosition = - maybe (pure Nothing) \obj -> map Just $ - { startLine: _ - , startColumn: _ - , endLine: _ - , endColumn: _ - } <$> obj .: "startLine" - <*> obj .: "startColumn" - <*> obj .: "endLine" - <*> obj .: "endColumn" - -encodePosition :: Position -> Json -encodePosition = unsafeCoerce - -parseSuggestion :: Maybe (FO.Object Json) -> Either String (Maybe Suggestion) -parseSuggestion = - maybe (pure Nothing) \obj -> map Just $ - { replacement: _ - , replaceRange: _ - } <$> obj .: "replacement" - <*> (obj .:? "replaceRange" >>= parsePosition) - -encodeSuggestion :: Suggestion -> Json -encodeSuggestion suggestion = encodeJson $ FO.runST do - obj <- FOST.new - _ <- FOST.poke "replacement" (encodeJson suggestion.replacement) obj - _ <- FOST.poke "replaceRange" (encodeJson (maybe jsonNull encodePosition suggestion.replaceRange)) obj - pure obj - -maybeProp :: forall a. (DecodeJson a) => FO.Object Json -> String -> Either String (Maybe a) -maybeProp obj key = maybe (Right Nothing) (lmap printJsonDecodeError <<< decodeJson) (FO.lookup key obj) - -infix 7 maybeProp as .:? - -getField :: forall a. (DecodeJson a) => FO.Object Json -> String -> Either String a -getField obj key = lmap printJsonDecodeError (Decode.Combinators.getField obj key) - -infix 7 getField as .: +psaResultCodec :: CA.JsonCodec PsaResult +psaResultCodec = CAR.object "PsaResult" + { warnings: CA.array psaErrorCodec + , errors: CA.array psaErrorCodec + } + +psaErrorCodec :: CA.JsonCodec PsaError +psaErrorCodec = CAR.object "PsaError" + { moduleName: CAC.maybe CA.string + , errorCode: CA.string + , errorLink: CA.string + , message: CA.string + , filename: CAC.maybe CA.string + , position: CACompat.maybe positionCodec + , suggestion: CACompat.maybe suggestionCodec + } + +positionCodec :: CA.JsonCodec Position +positionCodec = CAR.object "Position" + { startLine: CA.int + , startColumn: CA.int + , endLine: CA.int + , endColumn: CA.int + } + +suggestionCodec :: CA.JsonCodec Suggestion +suggestionCodec = CAR.object "Suggestion" + { replacement: CA.string + , replaceRange: CACompat.maybe positionCodec + } From 77a9eecfa2e721ce592ad33119d83b6d6575ec2b Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 30 Mar 2023 02:35:29 -0500 Subject: [PATCH 09/78] Replace usage of iter_ --- spaghetto/src/Spago/Psa/Printer/Default.purs | 7 ++++--- spaghetto/src/Spago/Psa/Util.purs | 8 +------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/spaghetto/src/Spago/Psa/Printer/Default.purs b/spaghetto/src/Spago/Psa/Printer/Default.purs index 2dbd42d04..87d4f922d 100644 --- a/spaghetto/src/Spago/Psa/Printer/Default.purs +++ b/spaghetto/src/Spago/Psa/Printer/Default.purs @@ -20,6 +20,7 @@ import Data.Array as Array import Data.Foldable (sum, maximum) import Data.List.NonEmpty (NonEmptyList) import Data.Maybe (Maybe(..), fromMaybe) +import Data.FoldableWithIndex (forWithIndex_) import Data.String as Str import Data.Tuple (Tuple(..)) import Effect (Effect) @@ -28,16 +29,16 @@ import Foreign.Object as FO import Spago.Psa.Output (OutputStats, Output) import Spago.Psa.Printer (Rendered, AnsiText, ansiLength, renderSource, plain, style, indent, line, para, render) import Spago.Psa.Types (Lines, Position, PsaAnnotedError, PsaOptions, PsaPath(..), StatVerbosity(..)) -import Spago.Psa.Util (replicate, iter_) +import Spago.Psa.Util (replicate) -- | Prints output to the console. print :: PsaOptions -> Output -> Effect Unit print options output = do - iter_ output.warnings \i warning -> do + forWithIndex_ output.warnings \i warning -> do Console.error $ toString (renderWarning lenWarnings (i + 1) warning) Console.error "" - iter_ output.errors \i error -> do + forWithIndex_ output.errors \i error -> do Console.error $ toString (renderError lenErrors (i + 1) error) Console.error "" diff --git a/spaghetto/src/Spago/Psa/Util.purs b/spaghetto/src/Spago/Psa/Util.purs index 3ffced070..aca579464 100644 --- a/spaghetto/src/Spago/Psa/Util.purs +++ b/spaghetto/src/Spago/Psa/Util.purs @@ -7,9 +7,8 @@ module Spago.Psa.Util where import Prelude -import Data.Foldable (class Foldable, foldl) + import Data.String as Str -import Data.Tuple (Tuple(..), snd) replicate :: forall m. (Monoid m) => Int -> m -> m replicate n m = go n mempty @@ -23,8 +22,3 @@ padLeft width str = replicate (width - Str.length str) " " <> str padRight :: Int -> String -> String padRight width str = str <> replicate (width - Str.length str) " " - -iter_ :: forall m f a b. Foldable f => Applicative m => f a -> (Int -> a -> m b) -> m Unit -iter_ xs f = snd $ foldl go (Tuple 0 (pure unit)) xs - where - go (Tuple i a) b = Tuple (i + 1) (a <* f i b) From f64f630946eafa77b07783417dd8c06a8a3f12b5 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 30 Mar 2023 04:21:07 -0500 Subject: [PATCH 10/78] Migrate printer to Dodo printer --- spaghetto/src/Spago/Psa/Printer.purs | 47 ++-- spaghetto/src/Spago/Psa/Printer/Default.purs | 245 +++++++++++-------- 2 files changed, 171 insertions(+), 121 deletions(-) diff --git a/spaghetto/src/Spago/Psa/Printer.purs b/spaghetto/src/Spago/Psa/Printer.purs index 898fa0197..fc3640407 100644 --- a/spaghetto/src/Spago/Psa/Printer.purs +++ b/spaghetto/src/Spago/Psa/Printer.purs @@ -26,10 +26,13 @@ import Prim hiding (Row) import Ansi.Codes as Ansi import Ansi.Output (foreground, dim) import Data.Array as Array +import Data.Foldable (fold) import Data.List.NonEmpty (NonEmptyList) import Data.List.NonEmpty as NEL import Data.String as Str import Data.Tuple (uncurry) +import Dodo as D +import Dodo.Ansi as DA import Spago.Psa.Types (Position, Lines) import Spago.Psa.Util (replicate, padLeft) @@ -91,7 +94,7 @@ renderAnsi true (Plain s) = s renderAnsi true (Style g s) = Ansi.escapeCodeToString (Ansi.Graphics g) <> s <> Ansi.escapeCodeToString (Ansi.Graphics (NEL.singleton Ansi.Reset)) -renderSource :: Position -> Lines -> Rendered +renderSource :: Position -> Lines -> D.Doc Ansi.GraphicsParam renderSource pos lines = renderAnnotation (gutter + 2) pos source' where lineNums = Array.range pos.startLine pos.endLine @@ -99,37 +102,37 @@ renderSource pos lines = renderAnnotation (gutter + 2) pos source' source = uncurry (sourceLine gutter " ") <$> Array.zip lineNums lines source' = if Array.length source > 7 then Array.take 3 source - <> [ [ plain $ replicate (gutter + 2) " ", style dim "..." ] ] + <> [ (D.text $ replicate (gutter + 2) " ") <> (DA.dim $ D.text "..." ) ] <> Array.drop (Array.length source - 3) source else source -renderAnnotation :: Int -> Position -> Array (Array AnsiText) -> Rendered -renderAnnotation offset pos lines = para - case lines of +renderAnnotation :: Int -> Position -> Array (D.Doc Ansi.GraphicsParam) -> D.Doc Ansi.GraphicsParam +renderAnnotation offset pos lines = + D.lines case lines of [ l ] -> - [ line l - , line $ renderErrorRange (pos.startColumn + offset) (pos.endColumn - pos.startColumn) + [ l + , renderErrorRange (pos.startColumn + offset) (pos.endColumn - pos.startColumn) ] _ -> - [ line $ renderErrorTick (pos.startColumn + offset) "v" - , para (line <$> lines) - , line $ renderErrorTick (pos.endColumn + offset - 1) "^" + [ renderErrorTick (pos.startColumn + offset) "v" + , D.lines lines + , renderErrorTick (pos.endColumn + offset - 1) "^" ] -sourceLine :: Int -> String -> Int -> String -> Array AnsiText -sourceLine gutter sep num code = - [ style dim $ padLeft gutter (show num) <> sep - , plain code +sourceLine :: Int -> String -> Int -> String -> D.Doc Ansi.GraphicsParam +sourceLine gutter sep num code = fold + [ DA.dim $ D.text $ padLeft gutter (show num) <> sep + , D.text code ] -renderErrorRange :: Int -> Int -> Array AnsiText -renderErrorRange start len = - [ plain $ replicate (start - 1) " " - , style (foreground Ansi.Red) $ replicate len "^" +renderErrorRange :: Int -> Int -> D.Doc Ansi.GraphicsParam +renderErrorRange start len = fold + [ D.text $ replicate (start - 1) " " + , DA.foreground Ansi.Red $ D.text $ replicate len "^" ] -renderErrorTick :: Int -> String -> Array AnsiText -renderErrorTick start char = - [ plain $ replicate (start - 1) " " - , style (foreground Ansi.Red) char +renderErrorTick :: Int -> String -> D.Doc Ansi.GraphicsParam +renderErrorTick start char = fold + [ D.text $ replicate (start - 1) " " + , DA.foreground Ansi.Red $ D.text char ] diff --git a/spaghetto/src/Spago/Psa/Printer/Default.purs b/spaghetto/src/Spago/Psa/Printer/Default.purs index 87d4f922d..487b17aee 100644 --- a/spaghetto/src/Spago/Psa/Printer/Default.purs +++ b/spaghetto/src/Spago/Psa/Printer/Default.purs @@ -14,15 +14,20 @@ module Spago.Psa.Printer.Default import Prelude +import Control.Alternative as Alternative import Ansi.Codes as Ansi -import Ansi.Output (foreground, dim) import Data.Array as Array import Data.Foldable (sum, maximum) import Data.List.NonEmpty (NonEmptyList) -import Data.Maybe (Maybe(..), fromMaybe) +import Data.Maybe (Maybe(..), fromMaybe, maybe) +import Data.Monoid (power) +import Data.Foldable (fold, maximumBy, maximum, foldMap) import Data.FoldableWithIndex (forWithIndex_) +import Data.Unfoldable (unfoldr) import Data.String as Str import Data.Tuple (Tuple(..)) +import Dodo as D +import Dodo.Ansi as DA import Effect (Effect) import Effect.Console as Console import Foreign.Object as FO @@ -35,17 +40,19 @@ import Spago.Psa.Util (replicate) print :: PsaOptions -> Output -> Effect Unit print options output = do forWithIndex_ output.warnings \i warning -> do - Console.error $ toString (renderWarning lenWarnings (i + 1) warning) + Console.error $ printDoc (renderWarning lenWarnings (i + 1) warning) Console.error "" forWithIndex_ output.errors \i error -> do - Console.error $ toString (renderError lenErrors (i + 1) error) + Console.error $ printDoc (renderError lenErrors (i + 1) error) Console.error "" - Console.error $ toString (renderStats' output.stats) + Console.error $ printDoc (renderStats' output.stats) where - toString = render options.ansi + printDoc + | options.ansi = D.print DA.ansiGraphics D.twoSpaces + | otherwise = D.print D.plainText D.twoSpaces lenWarnings = Array.length output.warnings lenErrors = Array.length output.errors renderStats' = case options.statVerbosity of @@ -53,75 +60,63 @@ print options output = do CompactStats -> renderStats VerboseStats -> renderVerboseStats -renderWarning :: Int -> Int -> PsaAnnotedError -> Rendered -renderWarning = renderWrapper (foreground Ansi.Yellow) - -renderError :: Int -> Int -> PsaAnnotedError -> Rendered -renderError = renderWrapper (foreground Ansi.Red) - -renderWrapper :: NonEmptyList Ansi.GraphicsParam -> Int -> Int -> PsaAnnotedError -> Rendered -renderWrapper gfx total index { error, path, position, source, message } = - para - [ line $ - [ renderStatus gfx total index error.errorCode - , plain " " - , renderPath path error.moduleName - ] <> fromMaybe mempty (renderPosition <$> position) - , emptyLine - , indented - $ fromMaybe mempty (renderSource' <$> position <*> source) - <> toLines message +renderWarning :: Int -> Int -> PsaAnnotedError -> D.Doc Ansi.GraphicsParam +renderWarning = renderWrapper Ansi.Yellow + +renderError :: Int -> Int -> PsaAnnotedError -> D.Doc Ansi.GraphicsParam +renderError = renderWrapper Ansi.Red + +renderWrapper :: Ansi.Color -> Int -> Int -> PsaAnnotedError -> D.Doc Ansi.GraphicsParam +renderWrapper color total index { error, path, position, source, message } = + D.lines + [ D.words $ + [ renderStatus color total index error.errorCode + , renderPath path error.moduleName <> foldMap renderPosition position + ] + , D.text "" + , D.indent $ D.lines + [ fromMaybe mempty (renderSource' <$> position <*> source) + , toLines message + ] ] -toLines :: String -> Rendered -toLines = para <<< map (line <<< Array.singleton <<< plain) <<< Str.split (Str.Pattern "\n") +toLines :: String -> D.Doc Ansi.GraphicsParam +toLines = D.lines <<< map D.text <<< Str.split (Str.Pattern "\n") -emptyLine :: Rendered -emptyLine = line [ plain "" ] +renderStatus :: Ansi.Color -> Int -> Int -> String -> D.Doc Ansi.GraphicsParam +renderStatus color total index code = + DA.foreground color $ D.text $ "[" <> show index <> "/" <> show total <> " " <> code <> "]" -indented :: Rendered -> Rendered -indented = indent [ plain " " ] +renderModuleName :: Maybe String -> D.Doc Ansi.GraphicsParam +renderModuleName Nothing = DA.dim $ D.text "(unknown module)" +renderModuleName (Just m) = D.text m -renderStatus :: NonEmptyList Ansi.GraphicsParam -> Int -> Int -> String -> AnsiText -renderStatus gfx total index code = - style gfx $ "[" <> show index <> "/" <> show total <> " " <> code <> "]" - -renderModuleName :: Maybe String -> AnsiText -renderModuleName Nothing = style dim "(unknown module)" -renderModuleName (Just m) = plain m - -renderPath :: PsaPath -> Maybe String -> AnsiText -renderPath (Src f) _ = plain f -renderPath (Lib f) _ = plain f +renderPath :: PsaPath -> Maybe String -> D.Doc Ansi.GraphicsParam +renderPath (Src f) _ = D.text f +renderPath (Lib f) _ = D.text f renderPath _ m = renderModuleName m -renderPosition :: Position -> Array AnsiText -renderPosition pos = - [ style dim ":" - , plain (show pos.startLine) - , style dim ":" - , plain (show pos.startColumn) +renderPosition :: Position -> D.Doc Ansi.GraphicsParam +renderPosition pos = fold + [ DA.dim $ D.text ":" + , D.text $ show pos.startLine + , DA.dim $ D.text ":" + , D.text $ show pos.startColumn ] -renderSource' :: Position -> Lines -> Rendered -renderSource' pos lines = renderSource pos lines <> emptyLine +renderSource' :: Position -> Lines -> D.Doc Ansi.GraphicsParam +renderSource' pos lines = renderSource pos lines <> D.break -renderStats :: OutputStats -> Rendered +renderStats :: OutputStats -> D.Doc Ansi.GraphicsParam renderStats stats = renderStatCols - [ [ style (foreground Ansi.Yellow) "Warnings" ] - , [ style (foreground Ansi.Red) "Errors" ] - ] - [ renderStat srcWarnings - , renderStat srcErrors - ] - [ renderStat libWarnings - , renderStat libErrors - ] - [ renderStat allWarnings - , renderStat allErrors - ] + { col1: [ renderLabel Ansi.Yellow "Warnings", renderLabel Ansi.Red "Errors"] + , col2: [ renderStat srcWarnings, renderStat srcErrors ] + , col3: [ renderStat libWarnings, renderStat libErrors ] + , col4: [ renderStat allWarnings, renderStat allErrors ] + } where + renderLabel color lbl = { width: Str.length lbl, alignLeft: true, doc: DA.foreground color $ D.text lbl } sumRatio (Tuple a b) _ (Tuple c d) = Tuple (a + c) (b + d) srcWarnings = FO.fold sumRatio (Tuple 0 0) stats.srcWarnings srcErrors = FO.fold sumRatio (Tuple 0 0) stats.srcErrors @@ -130,19 +125,26 @@ renderStats stats = allWarnings = FO.fold sumRatio (Tuple 0 0) stats.allWarnings allErrors = FO.fold sumRatio (Tuple 0 0) stats.allErrors -renderVerboseStats :: OutputStats -> Rendered +renderVerboseStats :: OutputStats -> D.Doc Ansi.GraphicsParam renderVerboseStats stats = renderStatCols - (warningLabels <> errorLabels) - (srcWarnings <> srcErrors) - (libWarnings <> libErrors) - (allWarnings <> allErrors) + { col1: warningLabels <> errorLabels + , col2: srcWarnings <> srcErrors + , col3: libWarnings <> libErrors + , col4: allWarnings <> allErrors + } where warnings = Array.sort (FO.keys stats.allWarnings) errors = Array.sort (FO.keys stats.allErrors) - warningLabels = Array.singleton <<< style (foreground Ansi.Yellow) <$> warnings - errorLabels = Array.singleton <<< style (foreground Ansi.Red) <$> errors + renderLabel color lbl = + { width: Str.length lbl + , alignLeft: true + , doc: DA.foreground color $ D.text lbl + } + + warningLabels = renderLabel Ansi.Yellow <$> warnings + errorLabels = renderLabel Ansi.Red <$> errors getStat key x = fromMaybe (Tuple 0 0) $ FO.lookup key x getStats ks x = (\k -> renderStat $ getStat k x) <$> ks @@ -154,34 +156,79 @@ renderVerboseStats stats = allWarnings = getStats warnings stats.allWarnings allErrors = getStats errors stats.allErrors -renderStatCols :: Array (Array AnsiText) -> Array (Array AnsiText) -> Array (Array AnsiText) -> Array (Array AnsiText) -> Rendered -renderStatCols col1 col2 col3 col4 = para $ - catRow - `map` alignLeft ([ [ plain "" ] ] <> col1) - `Array.zipWith ($)` - alignLeft ([ [ plain "Src" ] ] <> col2) - `Array.zipWith ($)` - alignLeft ([ [ plain "Lib" ] ] <> col3) - `Array.zipWith ($)` - alignLeft ([ [ plain "All" ] ] <> col4) - +renderStatCols + :: { col1 :: Array DocColumn + , col2 :: Array DocColumn + , col3 :: Array DocColumn + , col4 :: Array DocColumn + } + -> D.Doc Ansi.GraphicsParam +renderStatCols columns = + renderStatCols' $ columns + { col1 = Array.cons { width: 0, alignLeft: true, doc: mempty } columns.col1 + , col2 = Array.cons { width: 3, alignLeft: true, doc: D.text "Src" } columns.col2 + , col3 = Array.cons { width: 3, alignLeft: true, doc: D.text "Lib" } columns.col3 + , col4 = Array.cons { width: 3, alignLeft: true, doc: D.text "All" } columns.col4 + } + +type DocColumn = + { width :: Int + , alignLeft :: Boolean + , doc :: D.Doc Ansi.GraphicsParam + } + +renderStatCols' + :: { col1 :: Array DocColumn + , col2 :: Array DocColumn + , col3 :: Array DocColumn + , col4 :: Array DocColumn + } + -> D.Doc Ansi.GraphicsParam +renderStatCols' { col1, col2, col3, col4 } = D.lines rows where - gutter = [ plain " " ] - catRow c1 c2 c3 c4 = - line $ c1 <> gutter <> c2 <> gutter <> c3 <> gutter <> c4 - - lineLength = sum <<< map ansiLength - alignRight = align \a as -> Array.cons a as - alignLeft = align \a as -> Array.snoc as a - align f ls = map pad ls - where - max = fromMaybe 0 $ maximum (map lineLength ls) - pad l = f (plain $ replicate (max - lineLength l) " ") l - -renderStat :: Tuple Int Int -> Array AnsiText -renderStat (Tuple 0 0) = [ style (foreground Ansi.Green) "0" ] -renderStat (Tuple a b) | a == b = [ plain $ show a ] -renderStat (Tuple a b) = - [ plain $ show a - , style dim $ "/" <> show b - ] + maxColWidth :: Array DocColumn -> Int + maxColWidth = maybe 0 _.width <<< maximumBy (comparing _.width) + col1Width = maxColWidth col1 + col2Width = maxColWidth col2 + col3Width = maxColWidth col3 + col4Width = maxColWidth col4 + + numOfRows = fromMaybe 0 $ maximum $ map Array.length [ col1, col2, col3, col4 ] + guttered = D.foldWithSeparator (D.text " ") + + rows :: Array (D.Doc Ansi.GraphicsParam) + rows = flip unfoldr 0 buildRow + + buildColumn :: Array DocColumn -> Int -> Int -> Maybe (D.Doc Ansi.GraphicsParam) + buildColumn column colWidth rowIdx = do + { width, alignLeft, doc } <- Array.index column rowIdx + let + padding = colWidth - width + padText = D.text $ power " " padding + if padding == 0 then + pure doc + else if alignLeft then + pure $ doc <> padText + else + pure $ padText <> doc + + buildRow rowIdx = do + Alternative.guard (rowIdx /= numOfRows) + c1 <- buildColumn col1 col1Width rowIdx + c2 <- buildColumn col2 col2Width rowIdx + c3 <- buildColumn col3 col3Width rowIdx + c4 <- buildColumn col4 col4Width rowIdx + pure $ flip Tuple (rowIdx + 1) $ guttered [ c1, c2, c3, c4 ] + +renderStat :: Tuple Int Int -> DocColumn +renderStat (Tuple 0 0) = { width: 1, alignLeft: false, doc: DA.foreground Ansi.Green $ D.text "0" } +renderStat (Tuple a b) + | a == b = do + let aText = show a + { width: Str.length aText, alignLeft: false, doc: D.text aText } + | otherwise = do + let aText = show a + let bText = show b + let width = 1 + Str.length aText + Str.length bText + { width, alignLeft: false, doc: fold [ D.text aText, DA.dim $ D.text "/", D.text bText ] } + From d974f42afedca7daae7ec3e368ce0796e9588707 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 30 Mar 2023 04:24:14 -0500 Subject: [PATCH 11/78] Inline used renderers into Default; drop printer --- spaghetto/src/Spago/Psa/Printer.purs | 138 ------------------- spaghetto/src/Spago/Psa/Printer/Default.purs | 48 ++++++- 2 files changed, 45 insertions(+), 141 deletions(-) delete mode 100644 spaghetto/src/Spago/Psa/Printer.purs diff --git a/spaghetto/src/Spago/Psa/Printer.purs b/spaghetto/src/Spago/Psa/Printer.purs deleted file mode 100644 index fc3640407..000000000 --- a/spaghetto/src/Spago/Psa/Printer.purs +++ /dev/null @@ -1,138 +0,0 @@ --- A majority of this code was copied from --- - https://github.com/natefaubion/purescript-psa-utils --- --- To fullfil license requirements --- Copyright © Nathan Faubion --- https://opensource.org/license/mit/ -module Spago.Psa.Printer - ( Row() - , line - , indent - , para - , AnsiText() - , plain - , style - , ansiLength - , Rendered - , render - , renderRow - , renderAnsi - , renderSource - ) where - -import Prelude -import Prim hiding (Row) - -import Ansi.Codes as Ansi -import Ansi.Output (foreground, dim) -import Data.Array as Array -import Data.Foldable (fold) -import Data.List.NonEmpty (NonEmptyList) -import Data.List.NonEmpty as NEL -import Data.String as Str -import Data.Tuple (uncurry) -import Dodo as D -import Dodo.Ansi as DA -import Spago.Psa.Types (Position, Lines) -import Spago.Psa.Util (replicate, padLeft) - -type Rendered = Row (Array AnsiText) - -data Row a - = Line a - | Indent a (Row a) - | Para (Array (Row a)) - -line :: forall a. a -> Row a -line = Line - -indent :: forall a. a -> Row a -> Row a -indent = Indent - -para :: forall a. Array (Row a) -> Row a -para = Para - -instance semigroupRow :: Semigroup (Row a) where - append a@(Line _) b@(Para bs) = Para (Array.cons a bs) - append a@(Indent _ _) b@(Para bs) = Para (Array.cons a bs) - append a@(Para as) b@(Line _) = Para (Array.snoc as b) - append a@(Para as) b@(Indent _ _) = Para (Array.snoc as b) - append a@(Para as) b@(Para bs) = Para (as <> bs) - append a b = Para [ a, b ] - -instance monoidRow :: Monoid (Row a) where - mempty = Para [] - -data AnsiText - = Plain String - | Style (NonEmptyList Ansi.GraphicsParam) String - -plain :: String -> AnsiText -plain = Plain - -style :: NonEmptyList Ansi.GraphicsParam -> String -> AnsiText -style = Style - -ansiLength :: AnsiText -> Int -ansiLength (Plain a) = Str.length a -ansiLength (Style _ a) = Str.length a - -render :: Boolean -> Rendered -> String -render ansi = renderRow (Str.joinWith "" <<< map (renderAnsi ansi)) - -renderRow :: forall a. (a -> String) -> Row a -> String -renderRow f = go "" - where - go ind (Line a) = ind <> f a - go ind (Para as) = Str.joinWith "\n" (go ind <$> as) - go ind (Indent i as) = go (ind <> f i) as - -renderAnsi :: Boolean -> AnsiText -> String -renderAnsi false (Plain s) = s -renderAnsi false (Style _ s) = s -renderAnsi true (Plain s) = s -renderAnsi true (Style g s) = - Ansi.escapeCodeToString (Ansi.Graphics g) <> s <> Ansi.escapeCodeToString (Ansi.Graphics (NEL.singleton Ansi.Reset)) - -renderSource :: Position -> Lines -> D.Doc Ansi.GraphicsParam -renderSource pos lines = renderAnnotation (gutter + 2) pos source' - where - lineNums = Array.range pos.startLine pos.endLine - gutter = Str.length (show pos.endLine) - source = uncurry (sourceLine gutter " ") <$> Array.zip lineNums lines - source' = - if Array.length source > 7 then Array.take 3 source - <> [ (D.text $ replicate (gutter + 2) " ") <> (DA.dim $ D.text "..." ) ] - <> Array.drop (Array.length source - 3) source - else source - -renderAnnotation :: Int -> Position -> Array (D.Doc Ansi.GraphicsParam) -> D.Doc Ansi.GraphicsParam -renderAnnotation offset pos lines = - D.lines case lines of - [ l ] -> - [ l - , renderErrorRange (pos.startColumn + offset) (pos.endColumn - pos.startColumn) - ] - _ -> - [ renderErrorTick (pos.startColumn + offset) "v" - , D.lines lines - , renderErrorTick (pos.endColumn + offset - 1) "^" - ] - -sourceLine :: Int -> String -> Int -> String -> D.Doc Ansi.GraphicsParam -sourceLine gutter sep num code = fold - [ DA.dim $ D.text $ padLeft gutter (show num) <> sep - , D.text code - ] - -renderErrorRange :: Int -> Int -> D.Doc Ansi.GraphicsParam -renderErrorRange start len = fold - [ D.text $ replicate (start - 1) " " - , DA.foreground Ansi.Red $ D.text $ replicate len "^" - ] - -renderErrorTick :: Int -> String -> D.Doc Ansi.GraphicsParam -renderErrorTick start char = fold - [ D.text $ replicate (start - 1) " " - , DA.foreground Ansi.Red $ D.text char - ] diff --git a/spaghetto/src/Spago/Psa/Printer/Default.purs b/spaghetto/src/Spago/Psa/Printer/Default.purs index 487b17aee..485548a64 100644 --- a/spaghetto/src/Spago/Psa/Printer/Default.purs +++ b/spaghetto/src/Spago/Psa/Printer/Default.purs @@ -19,22 +19,22 @@ import Ansi.Codes as Ansi import Data.Array as Array import Data.Foldable (sum, maximum) import Data.List.NonEmpty (NonEmptyList) +import Data.List.NonEmpty as NEL import Data.Maybe (Maybe(..), fromMaybe, maybe) import Data.Monoid (power) import Data.Foldable (fold, maximumBy, maximum, foldMap) import Data.FoldableWithIndex (forWithIndex_) import Data.Unfoldable (unfoldr) import Data.String as Str -import Data.Tuple (Tuple(..)) +import Data.Tuple (Tuple(..), uncurry) import Dodo as D import Dodo.Ansi as DA import Effect (Effect) import Effect.Console as Console import Foreign.Object as FO import Spago.Psa.Output (OutputStats, Output) -import Spago.Psa.Printer (Rendered, AnsiText, ansiLength, renderSource, plain, style, indent, line, para, render) import Spago.Psa.Types (Lines, Position, PsaAnnotedError, PsaOptions, PsaPath(..), StatVerbosity(..)) -import Spago.Psa.Util (replicate) +import Spago.Psa.Util (replicate, padLeft) -- | Prints output to the console. print :: PsaOptions -> Output -> Effect Unit @@ -232,3 +232,45 @@ renderStat (Tuple a b) let width = 1 + Str.length aText + Str.length bText { width, alignLeft: false, doc: fold [ D.text aText, DA.dim $ D.text "/", D.text bText ] } +renderSource :: Position -> Lines -> D.Doc Ansi.GraphicsParam +renderSource pos lines = renderAnnotation (gutter + 2) pos source' + where + lineNums = Array.range pos.startLine pos.endLine + gutter = Str.length (show pos.endLine) + source = uncurry (sourceLine gutter " ") <$> Array.zip lineNums lines + source' = + if Array.length source > 7 then Array.take 3 source + <> [ (D.text $ replicate (gutter + 2) " ") <> (DA.dim $ D.text "..." ) ] + <> Array.drop (Array.length source - 3) source + else source + +renderAnnotation :: Int -> Position -> Array (D.Doc Ansi.GraphicsParam) -> D.Doc Ansi.GraphicsParam +renderAnnotation offset pos lines = + D.lines case lines of + [ l ] -> + [ l + , renderErrorRange (pos.startColumn + offset) (pos.endColumn - pos.startColumn) + ] + _ -> + [ renderErrorTick (pos.startColumn + offset) "v" + , D.lines lines + , renderErrorTick (pos.endColumn + offset - 1) "^" + ] + +sourceLine :: Int -> String -> Int -> String -> D.Doc Ansi.GraphicsParam +sourceLine gutter sep num code = fold + [ DA.dim $ D.text $ padLeft gutter (show num) <> sep + , D.text code + ] + +renderErrorRange :: Int -> Int -> D.Doc Ansi.GraphicsParam +renderErrorRange start len = fold + [ D.text $ replicate (start - 1) " " + , DA.foreground Ansi.Red $ D.text $ replicate len "^" + ] + +renderErrorTick :: Int -> String -> D.Doc Ansi.GraphicsParam +renderErrorTick start char = fold + [ D.text $ replicate (start - 1) " " + , DA.foreground Ansi.Red $ D.text char + ] From 4e9aa093339e2c4d365c3cf08f94c78d6e6ac9d5 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 30 Mar 2023 04:26:31 -0500 Subject: [PATCH 12/78] Replace replicate with power --- spaghetto/src/Spago/Psa/Printer/Default.purs | 10 +++++----- spaghetto/src/Spago/Psa/Util.purs | 12 +++--------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/spaghetto/src/Spago/Psa/Printer/Default.purs b/spaghetto/src/Spago/Psa/Printer/Default.purs index 485548a64..6bf84223f 100644 --- a/spaghetto/src/Spago/Psa/Printer/Default.purs +++ b/spaghetto/src/Spago/Psa/Printer/Default.purs @@ -34,7 +34,7 @@ import Effect.Console as Console import Foreign.Object as FO import Spago.Psa.Output (OutputStats, Output) import Spago.Psa.Types (Lines, Position, PsaAnnotedError, PsaOptions, PsaPath(..), StatVerbosity(..)) -import Spago.Psa.Util (replicate, padLeft) +import Spago.Psa.Util (padLeft) -- | Prints output to the console. print :: PsaOptions -> Output -> Effect Unit @@ -240,7 +240,7 @@ renderSource pos lines = renderAnnotation (gutter + 2) pos source' source = uncurry (sourceLine gutter " ") <$> Array.zip lineNums lines source' = if Array.length source > 7 then Array.take 3 source - <> [ (D.text $ replicate (gutter + 2) " ") <> (DA.dim $ D.text "..." ) ] + <> [ (D.text $ power " " (gutter + 2)) <> (DA.dim $ D.text "..." ) ] <> Array.drop (Array.length source - 3) source else source @@ -265,12 +265,12 @@ sourceLine gutter sep num code = fold renderErrorRange :: Int -> Int -> D.Doc Ansi.GraphicsParam renderErrorRange start len = fold - [ D.text $ replicate (start - 1) " " - , DA.foreground Ansi.Red $ D.text $ replicate len "^" + [ D.text $ power " " (start - 1) + , DA.foreground Ansi.Red $ D.text $ power "^" len ] renderErrorTick :: Int -> String -> D.Doc Ansi.GraphicsParam renderErrorTick start char = fold - [ D.text $ replicate (start - 1) " " + [ D.text $ power " " (start - 1) , DA.foreground Ansi.Red $ D.text char ] diff --git a/spaghetto/src/Spago/Psa/Util.purs b/spaghetto/src/Spago/Psa/Util.purs index aca579464..360ebe33e 100644 --- a/spaghetto/src/Spago/Psa/Util.purs +++ b/spaghetto/src/Spago/Psa/Util.purs @@ -9,16 +9,10 @@ module Spago.Psa.Util where import Prelude import Data.String as Str - -replicate :: forall m. (Monoid m) => Int -> m -> m -replicate n m = go n mempty - where - go i x - | i <= 0 = x - | otherwise = go (i - 1) (x <> m) +import Data.Monoid (power) padLeft :: Int -> String -> String -padLeft width str = replicate (width - Str.length str) " " <> str +padLeft width str = power " " (width - Str.length str) <> str padRight :: Int -> String -> String -padRight width str = str <> replicate (width - Str.length str) " " +padRight width str = str <> power " " (width - Str.length str) From cad4300e63e0783a0eb091f728ca817c4ac10221 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 30 Mar 2023 04:28:54 -0500 Subject: [PATCH 13/78] Inline only usage of padLeft; drop util --- spaghetto/src/Spago/Psa/Printer/Default.purs | 4 +++- spaghetto/src/Spago/Psa/Util.purs | 18 ------------------ 2 files changed, 3 insertions(+), 19 deletions(-) delete mode 100644 spaghetto/src/Spago/Psa/Util.purs diff --git a/spaghetto/src/Spago/Psa/Printer/Default.purs b/spaghetto/src/Spago/Psa/Printer/Default.purs index 6bf84223f..1297f7fdb 100644 --- a/spaghetto/src/Spago/Psa/Printer/Default.purs +++ b/spaghetto/src/Spago/Psa/Printer/Default.purs @@ -34,7 +34,6 @@ import Effect.Console as Console import Foreign.Object as FO import Spago.Psa.Output (OutputStats, Output) import Spago.Psa.Types (Lines, Position, PsaAnnotedError, PsaOptions, PsaPath(..), StatVerbosity(..)) -import Spago.Psa.Util (padLeft) -- | Prints output to the console. print :: PsaOptions -> Output -> Effect Unit @@ -274,3 +273,6 @@ renderErrorTick start char = fold [ D.text $ power " " (start - 1) , DA.foreground Ansi.Red $ D.text char ] + +padLeft :: Int -> String -> String +padLeft width str = power " " (width - Str.length str) <> str diff --git a/spaghetto/src/Spago/Psa/Util.purs b/spaghetto/src/Spago/Psa/Util.purs deleted file mode 100644 index 360ebe33e..000000000 --- a/spaghetto/src/Spago/Psa/Util.purs +++ /dev/null @@ -1,18 +0,0 @@ --- A majority of this code was copied from --- - https://github.com/natefaubion/purescript-psa-utils --- --- To fullfil license requirements --- Copyright © Nathan Faubion --- https://opensource.org/license/mit/ -module Spago.Psa.Util where - -import Prelude - -import Data.String as Str -import Data.Monoid (power) - -padLeft :: Int -> String -> String -padLeft width str = power " " (width - Str.length str) <> str - -padRight :: Int -> String -> String -padRight width str = str <> power " " (width - Str.length str) From c73e47d759a188f3cd51b264802001c48c36054c Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 30 Mar 2023 17:03:39 -0500 Subject: [PATCH 14/78] Extract PSA's main's logic; convert to Aff --- spaghetto/src/Spago/Psa.purs | 191 ++++++++++++----------------------- 1 file changed, 62 insertions(+), 129 deletions(-) diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index ec4bc68f7..aa6945107 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -15,7 +15,7 @@ import Data.Bifunctor (lmap) import Data.Codec.Argonaut as CA import Data.DateTime (DateTime) import Data.DateTime.Instant (toDateTime) -import Data.Either (Either(..)) +import Data.Either (Either(..), either) import Data.Foldable (foldr, fold, for_) import Data.Maybe (Maybe(..), maybe) import Data.Set as Set @@ -24,6 +24,8 @@ import Data.Traversable (traverse) import Data.Tuple (Tuple(..)) import Data.Version as Version import Effect (Effect) +import Effect.Aff (Aff, attempt) +import Effect.Class (liftEffect) import Effect.Console as Console import Effect.Exception (catchException, throw, throwException) import Effect.Now (now) @@ -33,11 +35,13 @@ import Node.ChildProcess as Child import Node.Encoding as Encoding import Node.FS.Stats as Stats import Node.FS.Sync as File +import Node.FS.Aff as FSA import Node.Path as Path import Node.Platform (Platform(Win32)) import Node.Process as Process import Node.Stream as Stream import Partial.Unsafe (unsafePartial) +import Spago.Cmd as Cmd import Spago.Psa.Types (PsaOptions, StatVerbosity(..), psaResultCodec, psaErrorCodec) import Spago.Psa.Output (output) import Spago.Psa.Printer.Default as DefaultPrinter @@ -145,114 +149,42 @@ parseOptions opts args = x { opts = x.opts { libDirs = [ "bower_components", ".spago" ] } } | otherwise = x -main :: Effect Unit -main = void do - cwd <- Process.cwd - argv <- Array.drop 2 <$> Process.argv - - { extra - , opts - , purs - , showSource - , stash - , stashFile - , jsonErrors - } <- parseOptions (defaultOptions { cwd = cwd }) argv - - libDirs <- traverse (Path.resolve [ cwd ] >>> map (_ <> Path.sep)) opts.libDirs - let - opts' = opts { libDirs = libDirs } - args = Array.cons "compile" $ Array.cons "--json-errors" extra - +usePsa :: ParseOptions -> Aff Unit +usePsa { extra, opts, purs, showSource, stash, stashFile, jsonErrors } = do stashData <- if stash then readStashFile stashFile else emptyStash - readPursVersion purs \pursVer -> do - let - outputStream = - -- As of 0.14.0, JSON errors/warnings are written to stdout, but - -- beforehand they were written to stderr. - -- - -- We need to use Tuple like this because prerelease versions compare - -- less than normal versions with the same major, minor, and patch - -- numbers according to the semver spec. - if Tuple (Version.major pursVer) (Version.minor pursVer) >= Tuple 0 14 then Stdout - else Stderr - spawn' outputStream purs args \pursResult -> do - for_ (Str.split (Str.Pattern "\n") pursResult.output) \err -> - case jsonParser err >>= CA.decode psaResultCodec >>> lmap CA.printJsonDecodeError of - Left _ -> Console.error err - Right out -> do - files <- Ref.new FO.empty - let - loadLinesImpl = if showSource then loadLines files else loadNothing - filenames = insertFilenames (insertFilenames Set.empty out.errors) out.warnings - merged <- mergeWarnings filenames stashData.date stashData.stash out.warnings - when stash $ writeStashFile stashFile merged - out' <- output loadLinesImpl opts' out { warnings = merged } - if jsonErrors then JsonPrinter.print out' - else DefaultPrinter.print opts' out' - if FO.isEmpty out'.stats.allErrors then Process.exit pursResult.exitCode - else Process.exit 1 + result <- Cmd.exec purs [ "compile", "--json-errors" ] Cmd.defaultExecOptions + let + result' = case result of + Left err -> { output: err.stdout, exitCode: err.exitCode } + Right success -> { output: success.stdout, exitCode: Just success.exitCode } + for_ (Str.split (Str.Pattern "\n") result'.output) \err -> + case jsonParser err >>= CA.decode psaResultCodec >>> lmap CA.printJsonDecodeError of + Left _ -> do + liftEffect $ Console.error err + Right out -> do + files <- liftEffect $ Ref.new FO.empty + let + loadLinesImpl = if showSource then loadLines files else loadNothing + filenames = insertFilenames (insertFilenames Set.empty out.errors) out.warnings + merged <- mergeWarnings filenames stashData.date stashData.stash out.warnings + when stash $ writeStashFile stashFile merged + + out' <- output loadLinesImpl opts out { warnings = merged } + + liftEffect $ if jsonErrors then JsonPrinter.print out' else DefaultPrinter.print opts out' + + liftEffect do + if FO.isEmpty out'.stats.allErrors then + for_ result'.exitCode Process.exit + else Process.exit 1 where insertFilenames = foldr \x s -> maybe s (flip Set.insert s) x.filename loadNothing _ _ = pure Nothing - spawn' outputStream cmd args onExit = do - let - stdio = - case outputStream of - Stdout -> [ Just Child.Pipe, Just Child.Pipe, unsafePartial (Array.unsafeIndex Child.inherit 2) ] - Stderr -> [ Just Child.Pipe, unsafePartial (Array.unsafeIndex Child.inherit 1), Just Child.Pipe ] - - child <- Child.spawn cmd args Child.defaultSpawnOptions { stdio = stdio } - buffer <- Ref.new "" - fillBuffer buffer $ - case outputStream of - Stdout -> Child.stdout child - Stderr -> Child.stderr child - Child.onExit child \status -> - case status of - Child.Normally n -> do - output <- Ref.read buffer - onExit { output, exitCode: n } - Child.BySignal s -> do - Console.error (show s) - Process.exit 1 - Child.onError child (retryWithCmd outputStream cmd args onExit) - - fillBuffer buffer stream = - Stream.onDataString stream Encoding.UTF8 \chunk -> - Ref.modify_ (_ <> chunk) buffer - - readPursVersion :: String -> (Version.Version -> Effect Unit) -> Effect Unit - readPursVersion purs cb = do - spawn' Stdout purs [ "--version" ] \{ output } -> do - let verStr = Str.takeWhile (_ /= Str.codePointFromChar ' ') $ Str.trim output - case Version.parseVersion verStr of - Right v -> - cb v - Left err -> do - throw $ fold - [ "Unable to parse the version from `purs`. (Saw: " - , verStr - , "). Please check that the right executable is on your PATH." - ] - - retryWithCmd outputStream cmd args onExit err - | err.code == "ENOENT" = do - -- On windows, if the executable wasn't found, try adding .cmd - if Process.platform == Just Win32 then - case Str.stripSuffix (Str.Pattern ".cmd") cmd of - Nothing -> spawn' outputStream (cmd <> ".cmd") args onExit - Just bareCmd -> throw $ "`" <> bareCmd <> "` executable not found. (nor `" <> cmd <> "`)" - else - throw $ "`" <> cmd <> "` executable not found." - | otherwise = - throwException (Child.toStandardError err) - isEmptySpan filename pos = filename == "" || pos.startLine == 0 && pos.endLine == 0 @@ -262,56 +194,57 @@ main = void do -- TODO: Handle exceptions loadLines files filename pos | isEmptySpan filename pos = pure Nothing - | otherwise = catchException (const (pure Nothing)) do - cache <- FO.lookup filename <$> Ref.read files - contents <- - case cache of - Just lines -> pure lines - Nothing -> do - lines <- Str.split (Str.Pattern "\n") <$> File.readTextFile Encoding.UTF8 filename - Ref.modify_ (FO.insert filename lines) files - pure lines - let source = Array.slice (pos.startLine - 1) (pos.endLine) contents - pure $ Just source + | otherwise = do + result <- attempt do + cache <- liftEffect $ FO.lookup filename <$> Ref.read files + contents <- + case cache of + Just lines -> pure lines + Nothing -> do + lines <- Str.split (Str.Pattern "\n") <$> FSA.readTextFile Encoding.UTF8 filename + liftEffect $ Ref.modify_ (FO.insert filename lines) files + pure lines + let source = Array.slice (pos.startLine - 1) (pos.endLine) contents + pure $ Just source + either (const (pure Nothing)) pure result decodeStash s = jsonParser s >>= CA.decode (CA.array psaErrorCodec) >>> lmap CA.printJsonDecodeError encodeStash s = CA.encode (CA.array psaErrorCodec) s - emptyStash :: forall a. Effect { date :: DateTime, stash :: Array a } - emptyStash = { date: _, stash: [] } <$> toDateTime <$> now + emptyStash :: forall a. Aff { date :: DateTime, stash :: Array a } + emptyStash = liftEffect $ { date: _, stash: [] } <$> toDateTime <$> now - readStashFile stashFile = catchException (const emptyStash) do - stat <- File.stat stashFile - file <- File.readTextFile Encoding.UTF8 stashFile - case decodeStash file of - Left _ -> emptyStash - Right stash -> pure { date: Stats.modifiedTime stat, stash } + readStashFile stashFile = do + result <- attempt do + stat <- FSA.stat stashFile + file <- FSA.readTextFile Encoding.UTF8 stashFile + case decodeStash file of + Left _ -> emptyStash + Right stash -> pure { date: Stats.modifiedTime stat, stash } + either (const emptyStash) pure $ result writeStashFile stashFile warnings = do let file = stringify (encodeStash warnings) - File.writeTextFile Encoding.UTF8 stashFile file + FSA.writeTextFile Encoding.UTF8 stashFile file mergeWarnings filenames date old new = do - fileStat <- Ref.new FO.empty + fileStat <- liftEffect $ Ref.new FO.empty old' <- flip Array.filterA old \x -> case x.filename of Nothing -> pure false Just f -> if Set.member f filenames then pure false else do - stat <- FO.lookup f <$> Ref.read fileStat + stat <- liftEffect $ FO.lookup f <$> Ref.read fileStat case stat of Just s -> pure s Nothing -> do - s <- catchException (\_ -> pure false) $ - (date > _) <<< Stats.modifiedTime <$> File.stat f - _ <- Ref.modify_ (FO.insert f s) fileStat - pure s + s <- attempt $ (date > _) <<< Stats.modifiedTime <$> FSA.stat f + let s' = either (const false) identity s + _ <- liftEffect $ Ref.modify_ (FO.insert f s') fileStat + pure s' pure $ old' <> new --- Indicates which output stream we are interested in when spawning a child process. -data OutputStream = Stdout | Stderr - usage :: String usage = """psa - Error/Warning reporting frontend for 'purs compile' From 2bdb7d3a32506538faf09b8f44f46946c13c6262 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 30 Mar 2023 17:09:20 -0500 Subject: [PATCH 15/78] Remove irrelevant args from ParseOptions --- spaghetto/src/Spago/Psa.purs | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index aa6945107..a6d5402b0 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -62,9 +62,7 @@ defaultOptions = } type ParseOptions = - { extra :: Array String - , opts :: PsaOptions - , purs :: String + { opts :: PsaOptions , showSource :: Boolean , stash :: Boolean , stashFile :: String @@ -78,9 +76,7 @@ parseOptions parseOptions opts args = defaultLibDir <$> Array.foldM parse - { extra: [] - , purs: "purs" - , showSource: true + { showSource: true , stash: false , stashFile: ".psa-stash" , jsonErrors: false @@ -131,13 +127,10 @@ parseOptions opts args = | isPrefix "--is-lib=" arg = pure p { opts = p.opts { libDirs = Array.snoc p.opts.libDirs (Str.drop 9 arg) } } - | isPrefix "--purs=" arg = - pure p { purs = Str.drop 7 arg } - | isPrefix "--stash=" arg = pure p { stash = true, stashFile = Str.drop 8 arg } - | otherwise = pure p { extra = Array.snoc p.extra arg } + | otherwise = pure p isPrefix s str = case Str.indexOf (Str.Pattern s) str of @@ -150,12 +143,12 @@ parseOptions opts args = | otherwise = x usePsa :: ParseOptions -> Aff Unit -usePsa { extra, opts, purs, showSource, stash, stashFile, jsonErrors } = do +usePsa { opts, showSource, stash, stashFile, jsonErrors } = do stashData <- if stash then readStashFile stashFile else emptyStash - result <- Cmd.exec purs [ "compile", "--json-errors" ] Cmd.defaultExecOptions + result <- Cmd.exec "purs" [ "compile", "--json-errors" ] Cmd.defaultExecOptions let result' = case result of Left err -> { output: err.stdout, exitCode: err.exitCode } @@ -253,7 +246,6 @@ Usage: psa [--censor-lib] [--censor-src] [--censor-codes=CODES] [--filter-codes=CODES] [--no-colors] [--no-source] [--is-lib=DIR] [--purs=PURS] [--stash] - PSC_OPTIONS Available options: -h,--help Show this help text @@ -270,8 +262,6 @@ Available options: --stash Enable persistent warnings (defaults to .psa-stash) --stash=FILE Enable persistent warnings using a specific stash file --is-lib=DIR Distinguishing library path (defaults to 'bower_components') - --purs=PURS Name of purs executable (defaults to 'purs') CODES Comma-separated list of purs error codes - PSC_OPTIONS Any extra options are passed to 'purs compile' """ From 809fb4ec6e986ad3a4a8604be001082b37821899 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 30 Mar 2023 17:09:37 -0500 Subject: [PATCH 16/78] Drop help arg --- spaghetto/src/Spago/Psa.purs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index a6d5402b0..1b7dd7f02 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -85,9 +85,6 @@ parseOptions opts args = args where parse p arg - | arg == "--help" || arg == "-h" = - Console.log usage *> Process.exit 0 - | arg == "--stash" = pure p { stash = true } @@ -248,7 +245,6 @@ Usage: psa [--censor-lib] [--censor-src] [--is-lib=DIR] [--purs=PURS] [--stash] Available options: - -h,--help Show this help text --verbose-stats Show counts for each warning type --censor-stats Censor warning/error summary --censor-warnings Censor all warnings From 56527b94dc207d6dfac7cda7a83fafd6e899fac5 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Sat, 1 Apr 2023 06:11:35 -0500 Subject: [PATCH 17/78] Psa - Cleanup imports --- spaghetto/src/Spago/Psa.purs | 12 +----------- spaghetto/src/Spago/Psa/Printer/Default.purs | 17 +++++++---------- spaghetto/src/Spago/Psa/Types.purs | 9 +-------- 3 files changed, 9 insertions(+), 29 deletions(-) diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index 1b7dd7f02..a9875b7ec 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -16,31 +16,21 @@ import Data.Codec.Argonaut as CA import Data.DateTime (DateTime) import Data.DateTime.Instant (toDateTime) import Data.Either (Either(..), either) -import Data.Foldable (foldr, fold, for_) +import Data.Foldable (foldr, for_) import Data.Maybe (Maybe(..), maybe) import Data.Set as Set import Data.String as Str -import Data.Traversable (traverse) -import Data.Tuple (Tuple(..)) -import Data.Version as Version import Effect (Effect) import Effect.Aff (Aff, attempt) import Effect.Class (liftEffect) import Effect.Console as Console -import Effect.Exception (catchException, throw, throwException) import Effect.Now (now) import Effect.Ref as Ref import Foreign.Object as FO -import Node.ChildProcess as Child import Node.Encoding as Encoding import Node.FS.Stats as Stats -import Node.FS.Sync as File import Node.FS.Aff as FSA -import Node.Path as Path -import Node.Platform (Platform(Win32)) import Node.Process as Process -import Node.Stream as Stream -import Partial.Unsafe (unsafePartial) import Spago.Cmd as Cmd import Spago.Psa.Types (PsaOptions, StatVerbosity(..), psaResultCodec, psaErrorCodec) import Spago.Psa.Output (output) diff --git a/spaghetto/src/Spago/Psa/Printer/Default.purs b/spaghetto/src/Spago/Psa/Printer/Default.purs index 1297f7fdb..5b539c6eb 100644 --- a/spaghetto/src/Spago/Psa/Printer/Default.purs +++ b/spaghetto/src/Spago/Psa/Printer/Default.purs @@ -17,12 +17,9 @@ import Prelude import Control.Alternative as Alternative import Ansi.Codes as Ansi import Data.Array as Array -import Data.Foldable (sum, maximum) -import Data.List.NonEmpty (NonEmptyList) -import Data.List.NonEmpty as NEL +import Data.Foldable (fold, foldMap, maximum, maximumBy) import Data.Maybe (Maybe(..), fromMaybe, maybe) import Data.Monoid (power) -import Data.Foldable (fold, maximumBy, maximum, foldMap) import Data.FoldableWithIndex (forWithIndex_) import Data.Unfoldable (unfoldr) import Data.String as Str @@ -109,7 +106,7 @@ renderSource' pos lines = renderSource pos lines <> D.break renderStats :: OutputStats -> D.Doc Ansi.GraphicsParam renderStats stats = renderStatCols - { col1: [ renderLabel Ansi.Yellow "Warnings", renderLabel Ansi.Red "Errors"] + { col1: [ renderLabel Ansi.Yellow "Warnings", renderLabel Ansi.Red "Errors" ] , col2: [ renderStat srcWarnings, renderStat srcErrors ] , col3: [ renderStat libWarnings, renderStat libErrors ] , col4: [ renderStat allWarnings, renderStat allErrors ] @@ -136,7 +133,7 @@ renderVerboseStats stats = warnings = Array.sort (FO.keys stats.allWarnings) errors = Array.sort (FO.keys stats.allErrors) - renderLabel color lbl = + renderLabel color lbl = { width: Str.length lbl , alignLeft: true , doc: DA.foreground color $ D.text lbl @@ -162,7 +159,7 @@ renderStatCols , col4 :: Array DocColumn } -> D.Doc Ansi.GraphicsParam -renderStatCols columns = +renderStatCols columns = renderStatCols' $ columns { col1 = Array.cons { width: 0, alignLeft: true, doc: mempty } columns.col1 , col2 = Array.cons { width: 3, alignLeft: true, doc: D.text "Src" } columns.col2 @@ -201,7 +198,7 @@ renderStatCols' { col1, col2, col3, col4 } = D.lines rows buildColumn :: Array DocColumn -> Int -> Int -> Maybe (D.Doc Ansi.GraphicsParam) buildColumn column colWidth rowIdx = do { width, alignLeft, doc } <- Array.index column rowIdx - let + let padding = colWidth - width padText = D.text $ power " " padding if padding == 0 then @@ -239,12 +236,12 @@ renderSource pos lines = renderAnnotation (gutter + 2) pos source' source = uncurry (sourceLine gutter " ") <$> Array.zip lineNums lines source' = if Array.length source > 7 then Array.take 3 source - <> [ (D.text $ power " " (gutter + 2)) <> (DA.dim $ D.text "..." ) ] + <> [ (D.text $ power " " (gutter + 2)) <> (DA.dim $ D.text "...") ] <> Array.drop (Array.length source - 3) source else source renderAnnotation :: Int -> Position -> Array (D.Doc Ansi.GraphicsParam) -> D.Doc Ansi.GraphicsParam -renderAnnotation offset pos lines = +renderAnnotation offset pos lines = D.lines case lines of [ l ] -> [ l diff --git a/spaghetto/src/Spago/Psa/Types.purs b/spaghetto/src/Spago/Psa/Types.purs index 80360b8ae..f09ccb86b 100644 --- a/spaghetto/src/Spago/Psa/Types.purs +++ b/spaghetto/src/Spago/Psa/Types.purs @@ -24,20 +24,13 @@ module Spago.Psa.Types import Prelude -import Data.Argonaut.Core (Json) import Data.Codec.Argonaut.Record as CAR import Data.Codec.Argonaut as CA import Data.Codec.Argonaut.Common as CAC import Data.Codec.Argonaut.Compat as CACompat -import Data.Bifunctor (lmap) -import Data.Either (Either(..)) -import Data.Maybe (Maybe(..), maybe) +import Data.Maybe (Maybe(..)) import Data.Set (Set) -import Data.Traversable (traverse) import Data.Tuple (Tuple(..)) -import Foreign.Object as FO -import Foreign.Object.ST as FOST -import Unsafe.Coerce (unsafeCoerce) type ErrorCode = String type ModuleName = String From 26b7cf9e3130db0e5d3b291c929f4484bee90308 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Sat, 1 Apr 2023 06:13:19 -0500 Subject: [PATCH 18/78] Psa - fix shadow named warning --- spaghetto/src/Spago/Psa.purs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index a9875b7ec..b19c8b5c1 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -194,18 +194,18 @@ usePsa { opts, showSource, stash, stashFile, jsonErrors } = do emptyStash :: forall a. Aff { date :: DateTime, stash :: Array a } emptyStash = liftEffect $ { date: _, stash: [] } <$> toDateTime <$> now - readStashFile stashFile = do + readStashFile stashFile' = do result <- attempt do - stat <- FSA.stat stashFile - file <- FSA.readTextFile Encoding.UTF8 stashFile + stat <- FSA.stat stashFile' + file <- FSA.readTextFile Encoding.UTF8 stashFile' case decodeStash file of Left _ -> emptyStash - Right stash -> pure { date: Stats.modifiedTime stat, stash } + Right stash' -> pure { date: Stats.modifiedTime stat, stash: stash' } either (const emptyStash) pure $ result - writeStashFile stashFile warnings = do + writeStashFile stashFile' warnings = do let file = stringify (encodeStash warnings) - FSA.writeTextFile Encoding.UTF8 stashFile file + FSA.writeTextFile Encoding.UTF8 stashFile' file mergeWarnings filenames date old new = do fileStat <- liftEffect $ Ref.new FO.empty From 6580d489309592c2c14c9a521f41452716655699 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Sat, 1 Apr 2023 06:13:39 -0500 Subject: [PATCH 19/78] Psa - drop unused unexported declarations --- spaghetto/src/Spago/Psa/Output.purs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/spaghetto/src/Spago/Psa/Output.purs b/spaghetto/src/Spago/Psa/Output.purs index 17a20e2db..c52405349 100644 --- a/spaghetto/src/Spago/Psa/Output.purs +++ b/spaghetto/src/Spago/Psa/Output.purs @@ -123,13 +123,6 @@ annotatedError path lines error = { path, position, message, source, error } message = trimMessage error.message source = (\p -> Array.take (p.endLine - p.startLine + 1)) <$> position <*> lines -partition :: forall a. (a -> Boolean) -> Array a -> { pass :: Array a, fail :: Array a } -partition f = foldl go { pass: [], fail: [] } - where - go { pass, fail } x = - if f x then { pass: Array.snoc pass x, fail } - else { pass, fail: Array.snoc fail x } - updateStats :: ErrorTag -> PsaPath @@ -187,10 +180,6 @@ isSrc :: PsaPath -> Boolean isSrc (Src _) = true isSrc _ = false -isWarning :: ErrorTag -> Boolean -isWarning Warning = true -isWarning _ = false - -- | Finds the true bounds of the source. The PureScript compiler is greedy -- | when it comes to matching whitespace at the end of an expression, so the -- | original source bounds always includes whitespace and comments. From fc57688b705a28960bfce7f89f6443d02a4ee1e6 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Sat, 1 Apr 2023 06:13:49 -0500 Subject: [PATCH 20/78] Psa - fix more compiler warnings --- spaghetto/src/Spago/Psa/Output.purs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/spaghetto/src/Spago/Psa/Output.purs b/spaghetto/src/Spago/Psa/Output.purs index c52405349..cdf9008ac 100644 --- a/spaghetto/src/Spago/Psa/Output.purs +++ b/spaghetto/src/Spago/Psa/Output.purs @@ -164,13 +164,13 @@ errorPath libDirs path short = _ -> false onTag :: forall a b. (a -> b) -> (a -> b) -> ErrorTag -> a -> b -onTag f g Error x = f x -onTag f g Warning x = g x +onTag f _ Error x = f x +onTag _ g Warning x = g x onPath :: forall a. (a -> a) -> (a -> a) -> PsaPath -> a -> a -onPath f g (Src _) x = f x -onPath f g (Lib _) x = g x -onPath f g _ x = x +onPath f _ (Src _) x = f x +onPath _ g (Lib _) x = g x +onPath _ _ _ x = x isLib :: PsaPath -> Boolean isLib (Lib _) = true From d2872983c977ecca40ae9aa902b36de3887e4354 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Sat, 1 Apr 2023 04:23:40 -0500 Subject: [PATCH 21/78] Rename PsaOptions to PsaOutputOptions --- spaghetto/src/Spago/Psa.purs | 8 ++++---- spaghetto/src/Spago/Psa/Output.purs | 6 +++--- spaghetto/src/Spago/Psa/Printer/Default.purs | 4 ++-- spaghetto/src/Spago/Psa/Types.purs | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index b19c8b5c1..50634b239 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -32,12 +32,12 @@ import Node.FS.Stats as Stats import Node.FS.Aff as FSA import Node.Process as Process import Spago.Cmd as Cmd -import Spago.Psa.Types (PsaOptions, StatVerbosity(..), psaResultCodec, psaErrorCodec) +import Spago.Psa.Types (PsaOutputOptions, StatVerbosity(..), psaResultCodec, psaErrorCodec) import Spago.Psa.Output (output) import Spago.Psa.Printer.Default as DefaultPrinter import Spago.Psa.Printer.Json as JsonPrinter -defaultOptions :: PsaOptions +defaultOptions :: PsaOutputOptions defaultOptions = { ansi: true , censorWarnings: false @@ -52,7 +52,7 @@ defaultOptions = } type ParseOptions = - { opts :: PsaOptions + { opts :: PsaOutputOptions , showSource :: Boolean , stash :: Boolean , stashFile :: String @@ -60,7 +60,7 @@ type ParseOptions = } parseOptions - :: PsaOptions + :: PsaOutputOptions -> Array String -> Effect ParseOptions parseOptions opts args = diff --git a/spaghetto/src/Spago/Psa/Output.purs b/spaghetto/src/Spago/Psa/Output.purs index cdf9008ac..4d782d73d 100644 --- a/spaghetto/src/Spago/Psa/Output.purs +++ b/spaghetto/src/Spago/Psa/Output.purs @@ -23,7 +23,7 @@ import Data.String as Str import Data.Tuple (Tuple(..)) import Foreign.Object as FO import Node.Path as Path -import Spago.Psa.Types (PsaOptions, PsaError, PsaAnnotedError, PsaPath(..), PsaResult, Position, Filename, Lines, compareByLocation) +import Spago.Psa.Types (PsaOutputOptions, PsaError, PsaAnnotedError, PsaPath(..), PsaResult, Position, Filename, Lines, compareByLocation) data ErrorTag = Error | Warning @@ -61,7 +61,7 @@ output :: forall m . (Monad m) => (Filename -> Position -> m (Maybe Lines)) - -> PsaOptions + -> PsaOutputOptions -> PsaResult -> m Output output loadLines options result = do @@ -145,7 +145,7 @@ updateStats tag path code printed s = alterStat Nothing = Just (bump (Tuple 0 0)) alterStat (Just x) = Just (bump x) -shouldShowError :: PsaOptions -> ErrorTag -> PsaPath -> String -> Boolean +shouldShowError :: PsaOutputOptions -> ErrorTag -> PsaPath -> String -> Boolean shouldShowError _ Error _ _ = true shouldShowError { filterCodes, censorCodes, censorSrc, censorLib, censorWarnings } _ path code = not censorWarnings diff --git a/spaghetto/src/Spago/Psa/Printer/Default.purs b/spaghetto/src/Spago/Psa/Printer/Default.purs index 5b539c6eb..5865d6d30 100644 --- a/spaghetto/src/Spago/Psa/Printer/Default.purs +++ b/spaghetto/src/Spago/Psa/Printer/Default.purs @@ -30,10 +30,10 @@ import Effect (Effect) import Effect.Console as Console import Foreign.Object as FO import Spago.Psa.Output (OutputStats, Output) -import Spago.Psa.Types (Lines, Position, PsaAnnotedError, PsaOptions, PsaPath(..), StatVerbosity(..)) +import Spago.Psa.Types (Lines, Position, PsaAnnotedError, PsaOutputOptions, PsaPath(..), StatVerbosity(..)) -- | Prints output to the console. -print :: PsaOptions -> Output -> Effect Unit +print :: PsaOutputOptions -> Output -> Effect Unit print options output = do forWithIndex_ output.warnings \i warning -> do Console.error $ printDoc (renderWarning lenWarnings (i + 1) warning) diff --git a/spaghetto/src/Spago/Psa/Types.purs b/spaghetto/src/Spago/Psa/Types.purs index f09ccb86b..6a57a6dff 100644 --- a/spaghetto/src/Spago/Psa/Types.purs +++ b/spaghetto/src/Spago/Psa/Types.purs @@ -9,7 +9,7 @@ module Spago.Psa.Types , ModuleName , Filename , StatVerbosity(..) - , PsaOptions + , PsaOutputOptions , PsaResult , PsaError , PsaAnnotedError @@ -52,7 +52,7 @@ derive instance Eq PsaPath derive instance Ord PsaPath -type PsaOptions = +type PsaOutputOptions = { ansi :: Boolean , censorWarnings :: Boolean , censorLib :: Boolean From f15d5740722c24acbcc20c26e0cf2647b85de570 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Sat, 1 Apr 2023 06:18:09 -0500 Subject: [PATCH 22/78] Fix future shadowed name issue w/ Spago.Prelude --- spaghetto/src/Spago/Psa.purs | 4 ++-- spaghetto/src/Spago/Psa/Output.purs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index 50634b239..453bd7f48 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -33,7 +33,7 @@ import Node.FS.Aff as FSA import Node.Process as Process import Spago.Cmd as Cmd import Spago.Psa.Types (PsaOutputOptions, StatVerbosity(..), psaResultCodec, psaErrorCodec) -import Spago.Psa.Output (output) +import Spago.Psa.Output (buildOutput) import Spago.Psa.Printer.Default as DefaultPrinter import Spago.Psa.Printer.Json as JsonPrinter @@ -152,7 +152,7 @@ usePsa { opts, showSource, stash, stashFile, jsonErrors } = do merged <- mergeWarnings filenames stashData.date stashData.stash out.warnings when stash $ writeStashFile stashFile merged - out' <- output loadLinesImpl opts out { warnings = merged } + out' <- buildOutput loadLinesImpl opts out { warnings = merged } liftEffect $ if jsonErrors then JsonPrinter.print out' else DefaultPrinter.print opts out' diff --git a/spaghetto/src/Spago/Psa/Output.purs b/spaghetto/src/Spago/Psa/Output.purs index 4d782d73d..32815f30b 100644 --- a/spaghetto/src/Spago/Psa/Output.purs +++ b/spaghetto/src/Spago/Psa/Output.purs @@ -5,7 +5,7 @@ -- Copyright © Nathan Faubion -- https://opensource.org/license/mit/ module Spago.Psa.Output - ( output + ( buildOutput , Output , OutputStats , annotatedError @@ -57,14 +57,14 @@ initialStats = -- | positions, and semantic paths (lib vs src). The callback should load the -- | requested set of lines from the absolute filename based on the tentative -- | position information. -output +buildOutput :: forall m . (Monad m) => (Filename -> Position -> m (Maybe Lines)) -> PsaOutputOptions -> PsaResult -> m Output -output loadLines options result = do +buildOutput loadLines options result = do let result' = { warnings: pathOf <$> result.warnings From 4c4ab738cb65233ab0fc67186b45a868f13b607a Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Sat, 1 Apr 2023 04:23:40 -0500 Subject: [PATCH 23/78] Use psaCompile as a wrapper of purs compile --- spaghetto/src/Spago/Command/Build.purs | 14 ++- spaghetto/src/Spago/Psa.purs | 123 +++++++++++++++---------- spaghetto/src/Spago/Purs.purs | 9 +- 3 files changed, 86 insertions(+), 60 deletions(-) diff --git a/spaghetto/src/Spago/Command/Build.purs b/spaghetto/src/Spago/Command/Build.purs index 24a09fe79..5ee3d0bbe 100644 --- a/spaghetto/src/Spago/Command/Build.purs +++ b/spaghetto/src/Spago/Command/Build.purs @@ -14,8 +14,8 @@ import Spago.Cmd as Cmd import Spago.Config (Package(..), WithTestGlobs(..), Workspace, WorkspacePackage) import Spago.Config as Config import Spago.Git (Git) +import Spago.Psa as Psa import Spago.Purs (Purs) -import Spago.Purs as Purs import Spago.Purs.Graph as Graph type BuildEnv a = @@ -69,11 +69,18 @@ run opts = do Nothing -> args Just output -> args <> [ "--output", output ] + -- find the output flag and die if it's there - Spago handles it + when (isJust $ Cmd.findFlag { flags: [ "--json-errors" ], args: opts.pursArgs }) do + die + [ "Can't pass `--json-errors` option directly to purs." + , "Use the --json-errors flag for Spago, or add it to your config file." + ] + let buildBackend globs = do case workspace.backend of Nothing -> - Purs.compile globs (addOutputArgs opts.pursArgs) + Psa.psaCompile globs (addOutputArgs opts.pursArgs) Just backend -> do when (isJust $ Cmd.findFlag { flags: [ "-g", "--codegen" ], args: opts.pursArgs }) do die @@ -81,7 +88,8 @@ run opts = do , "Hint: No need to pass `--codegen corefn` explicitly when using the `backend` option." , "Remove the argument to solve the error" ] - Purs.compile globs $ (addOutputArgs opts.pursArgs) <> [ "--codegen", "corefn" ] + let args = (addOutputArgs opts.pursArgs) <> [ "--codegen", "corefn" ] + Psa.psaCompile globs args logInfo $ "Compiling with backend \"" <> backend.cmd <> "\"" logDebug $ "Running command `" <> backend.cmd <> "`" diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index 453bd7f48..ad77a091e 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -6,32 +6,24 @@ -- https://opensource.org/license/mit/ module Spago.Psa where -import Prelude +import Spago.Prelude import Data.Argonaut.Core (stringify) import Data.Argonaut.Parser (jsonParser) import Data.Array as Array -import Data.Bifunctor (lmap) import Data.Codec.Argonaut as CA -import Data.DateTime (DateTime) import Data.DateTime.Instant (toDateTime) -import Data.Either (Either(..), either) -import Data.Foldable (foldr, for_) -import Data.Maybe (Maybe(..), maybe) +import Data.Foldable (foldr) import Data.Set as Set +import Effect.Exception as Exception import Data.String as Str -import Effect (Effect) -import Effect.Aff (Aff, attempt) -import Effect.Class (liftEffect) -import Effect.Console as Console import Effect.Now (now) import Effect.Ref as Ref import Foreign.Object as FO import Node.Encoding as Encoding import Node.FS.Stats as Stats import Node.FS.Aff as FSA -import Node.Process as Process -import Spago.Cmd as Cmd +import Spago.Purs as Purs import Spago.Psa.Types (PsaOutputOptions, StatVerbosity(..), psaResultCodec, psaErrorCodec) import Spago.Psa.Output (buildOutput) import Spago.Psa.Printer.Default as DefaultPrinter @@ -51,6 +43,15 @@ defaultOptions = , cwd: "" } +defaultParseOptions :: ParseOptions +defaultParseOptions = + { showSource: true + , stash: false + , stashFile: ".psa-stash" + , jsonErrors: false + , opts: defaultOptions + } + type ParseOptions = { opts :: PsaOutputOptions , showSource :: Boolean @@ -60,19 +61,11 @@ type ParseOptions = } parseOptions - :: PsaOutputOptions - -> Array String + :: Array String -> Effect ParseOptions -parseOptions opts args = +parseOptions args = defaultLibDir <$> - Array.foldM parse - { showSource: true - , stash: false - , stashFile: ".psa-stash" - , jsonErrors: false - , opts - } - args + Array.foldM parse defaultParseOptions args where parse p arg | arg == "--stash" = @@ -129,21 +122,30 @@ parseOptions opts args = x { opts = x.opts { libDirs = [ "bower_components", ".spago" ] } } | otherwise = x -usePsa :: ParseOptions -> Aff Unit -usePsa { opts, showSource, stash, stashFile, jsonErrors } = do +psaCompile :: forall a. Set.Set FilePath -> Array String -> Spago (Purs.PursEnv a) Unit +psaCompile globs pursArgs = psaCompile' globs pursArgs defaultParseOptions + +psaCompile' :: forall a. Set.Set FilePath -> Array String -> ParseOptions -> Spago (Purs.PursEnv a) Unit +psaCompile' globs pursArgs { opts, showSource, stash, stashFile, jsonErrors } = do stashData <- if stash then readStashFile stashFile else emptyStash - result <- Cmd.exec "purs" [ "compile", "--json-errors" ] Cmd.defaultExecOptions + result <- Purs.compile globs (Array.snoc pursArgs "--json-errors") let result' = case result of - Left err -> { output: err.stdout, exitCode: err.exitCode } - Right success -> { output: success.stdout, exitCode: Just success.exitCode } - for_ (Str.split (Str.Pattern "\n") result'.output) \err -> + Left err -> { output: err.stdout, exitCode: err.exitCode, err: Just err } + Right success -> { output: success.stdout, exitCode: Just success.exitCode, err: Nothing } + arrErrorsIsEmpty <- forWithIndex (Str.split (Str.Pattern "\n") result'.output) \idx err -> case jsonParser err >>= CA.decode psaResultCodec >>> lmap CA.printJsonDecodeError of - Left _ -> do - liftEffect $ Console.error err + Left decodeErrMsg -> do + logDebug $ Array.intercalate "\n" + [ "Failed to decode PsaResult at index '" <> show idx <> "': " <> decodeErrMsg + , "Json was: " <> err + ] + -- Note to reviewer: + -- Should a stash decode error cause a non-zero exit? + pure false Right out -> do files <- liftEffect $ Ref.new FO.empty let @@ -156,32 +158,40 @@ usePsa { opts, showSource, stash, stashFile, jsonErrors } = do liftEffect $ if jsonErrors then JsonPrinter.print out' else DefaultPrinter.print opts out' - liftEffect do - if FO.isEmpty out'.stats.allErrors then - for_ result'.exitCode Process.exit - else Process.exit 1 + pure $ FO.isEmpty out'.stats.allErrors + + if Array.all identity arrErrorsIsEmpty then do + logSuccess "Build succeeded." + else do + for_ result'.err $ logDebug <<< show + die [ "Failed to build." ] where insertFilenames = foldr \x s -> maybe s (flip Set.insert s) x.filename loadNothing _ _ = pure Nothing isEmptySpan filename pos = - filename == "" || - pos.startLine == 0 && pos.endLine == 0 - && pos.startColumn == 0 - && pos.endColumn == 0 + filename == "" + || pos.startLine + == 0 + && pos.endLine + == 0 + && pos.startColumn + == 0 + && pos.endColumn + == 0 -- TODO: Handle exceptions loadLines files filename pos | isEmptySpan filename pos = pure Nothing | otherwise = do - result <- attempt do + result <- try do cache <- liftEffect $ FO.lookup filename <$> Ref.read files contents <- case cache of Just lines -> pure lines Nothing -> do - lines <- Str.split (Str.Pattern "\n") <$> FSA.readTextFile Encoding.UTF8 filename + lines <- liftAff $ Str.split (Str.Pattern "\n") <$> FSA.readTextFile Encoding.UTF8 filename liftEffect $ Ref.modify_ (FO.insert filename lines) files pure lines let source = Array.slice (pos.startLine - 1) (pos.endLine) contents @@ -191,21 +201,32 @@ usePsa { opts, showSource, stash, stashFile, jsonErrors } = do decodeStash s = jsonParser s >>= CA.decode (CA.array psaErrorCodec) >>> lmap CA.printJsonDecodeError encodeStash s = CA.encode (CA.array psaErrorCodec) s - emptyStash :: forall a. Aff { date :: DateTime, stash :: Array a } - emptyStash = liftEffect $ { date: _, stash: [] } <$> toDateTime <$> now + emptyStash = do + logDebug $ "Using empty stash" + liftEffect $ { date: _, stash: [] } <$> toDateTime <$> now readStashFile stashFile' = do - result <- attempt do - stat <- FSA.stat stashFile' - file <- FSA.readTextFile Encoding.UTF8 stashFile' + logDebug $ "About to read stash file: " <> stashFile' + result <- try do + stat <- liftAff $ FSA.stat stashFile' + file <- liftAff $ FSA.readTextFile Encoding.UTF8 stashFile' case decodeStash file of - Left _ -> emptyStash - Right stash' -> pure { date: Stats.modifiedTime stat, stash: stash' } - either (const emptyStash) pure $ result + Left err -> do + logDebug $ "Error decoding stash file: " <> err + emptyStash + Right stash' -> do + logDebug $ "Successfully decoded stash file" + pure { date: Stats.modifiedTime stat, stash: stash' } + case result of + Left err -> do + logDebug $ "Reading stash file failed: " <> Exception.message err + emptyStash + Right cache -> pure cache writeStashFile stashFile' warnings = do + logDebug $ "Writing stash file: " <> stashFile' let file = stringify (encodeStash warnings) - FSA.writeTextFile Encoding.UTF8 stashFile' file + liftAff $ FSA.writeTextFile Encoding.UTF8 stashFile' file mergeWarnings filenames date old new = do fileStat <- liftEffect $ Ref.new FO.empty @@ -219,7 +240,7 @@ usePsa { opts, showSource, stash, stashFile, jsonErrors } = do case stat of Just s -> pure s Nothing -> do - s <- attempt $ (date > _) <<< Stats.modifiedTime <$> FSA.stat f + s <- liftAff $ try $ (date > _) <<< Stats.modifiedTime <$> FSA.stat f let s' = either (const false) identity s _ <- liftEffect $ Ref.modify_ (FO.insert f s') fileStat pure s' diff --git a/spaghetto/src/Spago/Purs.purs b/spaghetto/src/Spago/Purs.purs index c5cd7d07a..e05de0f96 100644 --- a/spaghetto/src/Spago/Purs.purs +++ b/spaghetto/src/Spago/Purs.purs @@ -8,6 +8,7 @@ import Data.Codec.Argonaut.Record as CAR import Data.Profunctor as Profunctor import Data.Set as Set import Data.String as String +import Node.Library.Execa as Execa import Registry.Internal.Codec as Internal.Codec import Registry.Version as Version import Spago.Cmd as Cmd @@ -42,16 +43,12 @@ getPurs = where dropStuff pattern = fromMaybe "" <<< Array.head <<< String.split (String.Pattern pattern) -compile :: forall a. Set FilePath -> Array String -> Spago (PursEnv a) Unit +compile :: forall a. Set FilePath -> Array String -> Spago (PursEnv a) (Either Cmd.ExecError Cmd.ExecResult) compile globs pursArgs = do { purs } <- ask let args = [ "compile" ] <> pursArgs <> Set.toUnfoldable globs logDebug [ "Running command:", "purs " <> String.joinWith " " args ] - Cmd.exec purs.cmd args Cmd.defaultExecOptions >>= case _ of - Right _r -> logSuccess "Build succeeded." - Left err -> do - logDebug $ show err - die [ "Failed to build." ] + Cmd.exec purs.cmd args Cmd.defaultExecOptions -------------------------------------------------------------------------------- -- Graph From 4eefe9ddb6d417689301ad2f757b50c34666a7bc Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Sat, 1 Apr 2023 06:26:19 -0500 Subject: [PATCH 24/78] Pass libDirs into psaCompile --- spaghetto/src/Spago/Command/Build.purs | 5 +++-- spaghetto/src/Spago/Psa.purs | 15 ++++++--------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/spaghetto/src/Spago/Command/Build.purs b/spaghetto/src/Spago/Command/Build.purs index 5ee3d0bbe..99411ea4f 100644 --- a/spaghetto/src/Spago/Command/Build.purs +++ b/spaghetto/src/Spago/Command/Build.purs @@ -77,10 +77,11 @@ run opts = do ] let + psaLibDirs = [ "bower_components", ".spago" ] buildBackend globs = do case workspace.backend of Nothing -> - Psa.psaCompile globs (addOutputArgs opts.pursArgs) + Psa.psaCompile globs (addOutputArgs opts.pursArgs) psaLibDirs Just backend -> do when (isJust $ Cmd.findFlag { flags: [ "-g", "--codegen" ], args: opts.pursArgs }) do die @@ -89,7 +90,7 @@ run opts = do , "Remove the argument to solve the error" ] let args = (addOutputArgs opts.pursArgs) <> [ "--codegen", "corefn" ] - Psa.psaCompile globs args + Psa.psaCompile globs args psaLibDirs logInfo $ "Compiling with backend \"" <> backend.cmd <> "\"" logDebug $ "Running command `" <> backend.cmd <> "`" diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index ad77a091e..0db7edcfa 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -64,8 +64,7 @@ parseOptions :: Array String -> Effect ParseOptions parseOptions args = - defaultLibDir <$> - Array.foldM parse defaultParseOptions args + Array.foldM parse defaultParseOptions args where parse p arg | arg == "--stash" = @@ -117,13 +116,11 @@ parseOptions args = Just x | x == 0 -> true _ -> false - defaultLibDir x - | Array.length x.opts.libDirs == 0 = - x { opts = x.opts { libDirs = [ "bower_components", ".spago" ] } } - | otherwise = x - -psaCompile :: forall a. Set.Set FilePath -> Array String -> Spago (Purs.PursEnv a) Unit -psaCompile globs pursArgs = psaCompile' globs pursArgs defaultParseOptions +psaCompile :: forall a. Set.Set FilePath -> Array String -> Array String -> Spago (Purs.PursEnv a) Unit +psaCompile globs pursArgs libDirs = psaCompile' globs pursArgs + $ defaultParseOptions + { opts = defaultParseOptions.opts { libDirs = libDirs } + } psaCompile' :: forall a. Set.Set FilePath -> Array String -> ParseOptions -> Spago (Purs.PursEnv a) Unit psaCompile' globs pursArgs { opts, showSource, stash, stashFile, jsonErrors } = do From 55e3d02c3a2e6809476165e39f865e6f0701357f Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Fri, 31 Mar 2023 10:57:06 -0500 Subject: [PATCH 25/78] Refactor sourceGlob to include dir prefix --- spaghetto/src/Spago/Config.purs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/spaghetto/src/Spago/Config.purs b/spaghetto/src/Spago/Config.purs index 1adafc9ca..c63a9e927 100644 --- a/spaghetto/src/Spago/Config.purs +++ b/spaghetto/src/Spago/Config.purs @@ -12,6 +12,7 @@ module Spago.Config , getWorkspacePackages , readWorkspace , sourceGlob + , sourceGlob' , module Core ) where @@ -322,7 +323,10 @@ data WithTestGlobs | OnlyTestGlobs sourceGlob :: WithTestGlobs -> PackageName -> Package -> Array String -sourceGlob withTestGlobs name package = map (\p -> Path.concat [ getPackageLocation name package, p ]) +sourceGlob withTestGlobs name package = map _.glob $ sourceGlob' withTestGlobs name package + +sourceGlob' :: WithTestGlobs -> PackageName -> Package -> Array { globPrefix :: String, glob :: String } +sourceGlob' withTestGlobs name package = case package of WorkspacePackage { hasTests } -> case hasTests, withTestGlobs of @@ -331,14 +335,17 @@ sourceGlob withTestGlobs name package = map (\p -> Path.concat [ getPackageLocat true, OnlyTestGlobs -> [ testGlob ] true, NoTestGlobs -> [ srcGlob ] true, WithTestGlobs -> [ srcGlob, testGlob ] - GitPackage { subdir: Just s } -> [ Path.concat [ s, srcGlob ] ] + GitPackage { subdir: Just s } -> [ subdirSrcGlob s ] _ -> [ srcGlob ] - -srcGlob :: String -srcGlob = "src/**/*.purs" - -testGlob :: String -testGlob = "test/**/*.purs" + where + pkgLocation = getPackageLocation name package + srcGlob = fullDirGlob $ Path.concat [ pkgLocation, "src" ] + subdirSrcGlob subdir = fullDirGlob $ Path.concat [ pkgLocation, subdir, "src" ] + testGlob = fullDirGlob $ Path.concat [ pkgLocation, "test" ] + fullDirGlob dir = + { globPrefix: dir + , glob: Path.concat [ dir, "**/*.purs" ] + } getWorkspacePackages :: PackageSet -> Array WorkspacePackage getWorkspacePackages = Array.mapMaybe extractWorkspacePackage <<< Map.toUnfoldable From 727f4106ed6c220ea25fd9793760564c6f984fa4 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Fri, 31 Mar 2023 11:06:35 -0500 Subject: [PATCH 26/78] Extract lib dirs out of source globs --- spaghetto/src/Spago/Command/Build.purs | 11 +++++------ spaghetto/src/Spago/Config.purs | 20 +++++++++++--------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/spaghetto/src/Spago/Command/Build.purs b/spaghetto/src/Spago/Command/Build.purs index 99411ea4f..9b3c54c92 100644 --- a/spaghetto/src/Spago/Command/Build.purs +++ b/spaghetto/src/Spago/Command/Build.purs @@ -38,7 +38,7 @@ run opts = do { dependencies, workspace } <- ask let -- depsOnly means "no packages from the monorepo", so we filter out the workspace packages - dependencyGlobs = map (Tuple.uncurry $ Config.sourceGlob WithTestGlobs) case opts.depsOnly of + Tuple dependencyLibs dependencyGlobs = Array.unzip $ (Tuple.uncurry $ Config.sourceGlob' WithTestGlobs) =<< case opts.depsOnly of false -> Map.toUnfoldable dependencies true -> Map.toUnfoldable $ Map.filter ( case _ of @@ -48,7 +48,7 @@ run opts = do dependencies -- Here we select the right globs for a monorepo setup with a bunch of packages - projectSources = + projectSources = join if opts.depsOnly then [] else case workspace.selected of Just p -> [ workspacePackageGlob p ] @@ -77,11 +77,10 @@ run opts = do ] let - psaLibDirs = [ "bower_components", ".spago" ] buildBackend globs = do case workspace.backend of Nothing -> - Psa.psaCompile globs (addOutputArgs opts.pursArgs) psaLibDirs + Psa.psaCompile globs (addOutputArgs opts.pursArgs) dependencyLibs Just backend -> do when (isJust $ Cmd.findFlag { flags: [ "-g", "--codegen" ], args: opts.pursArgs }) do die @@ -90,7 +89,7 @@ run opts = do , "Remove the argument to solve the error" ] let args = (addOutputArgs opts.pursArgs) <> [ "--codegen", "corefn" ] - Psa.psaCompile globs args psaLibDirs + Psa.psaCompile globs args dependencyLibs logInfo $ "Compiling with backend \"" <> backend.cmd <> "\"" logDebug $ "Running command `" <> backend.cmd <> "`" @@ -114,7 +113,7 @@ run opts = do runCommands "Then" thenCommands -} - let globs = Set.fromFoldable $ join projectSources <> join dependencyGlobs <> [ BuildInfo.buildInfoPath ] + let globs = Set.fromFoldable $ projectSources <> dependencyGlobs <> [ BuildInfo.buildInfoPath ] buildBackend globs when workspace.buildOptions.pedanticPackages do diff --git a/spaghetto/src/Spago/Config.purs b/spaghetto/src/Spago/Config.purs index c63a9e927..8741f17da 100644 --- a/spaghetto/src/Spago/Config.purs +++ b/spaghetto/src/Spago/Config.purs @@ -323,9 +323,9 @@ data WithTestGlobs | OnlyTestGlobs sourceGlob :: WithTestGlobs -> PackageName -> Package -> Array String -sourceGlob withTestGlobs name package = map _.glob $ sourceGlob' withTestGlobs name package +sourceGlob withTestGlobs name package = map snd $ sourceGlob' withTestGlobs name package -sourceGlob' :: WithTestGlobs -> PackageName -> Package -> Array { globPrefix :: String, glob :: String } +sourceGlob' :: WithTestGlobs -> PackageName -> Package -> Array (Tuple String String) sourceGlob' withTestGlobs name package = case package of WorkspacePackage { hasTests } -> @@ -339,13 +339,15 @@ sourceGlob' withTestGlobs name package = _ -> [ srcGlob ] where pkgLocation = getPackageLocation name package - srcGlob = fullDirGlob $ Path.concat [ pkgLocation, "src" ] - subdirSrcGlob subdir = fullDirGlob $ Path.concat [ pkgLocation, subdir, "src" ] - testGlob = fullDirGlob $ Path.concat [ pkgLocation, "test" ] - fullDirGlob dir = - { globPrefix: dir - , glob: Path.concat [ dir, "**/*.purs" ] - } + srcGlob = Tuple + (Path.concat [ pkgLocation, "src" ]) + (Path.concat [ pkgLocation, "src/**/*.purs" ]) + subdirSrcGlob subdir = Tuple + (Path.concat [ pkgLocation, subdir, "src" ]) + (Path.concat [ pkgLocation, subdir, "src/**/*.purs" ]) + testGlob = Tuple + (Path.concat [ pkgLocation, "test" ]) + (Path.concat [ pkgLocation, "test/**/*.purs" ]) getWorkspacePackages :: PackageSet -> Array WorkspacePackage getWorkspacePackages = Array.mapMaybe extractWorkspacePackage <<< Map.toUnfoldable From 72e8416ae7a752f2ab3991d43c4fee779df1a6ab Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Sat, 1 Apr 2023 06:29:24 -0500 Subject: [PATCH 27/78] Inline psa output cwd arg into sole usage --- spaghetto/src/Spago/Psa.purs | 1 - spaghetto/src/Spago/Psa/Output.purs | 3 ++- spaghetto/src/Spago/Psa/Types.purs | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index 0db7edcfa..69df73675 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -40,7 +40,6 @@ defaultOptions = , statVerbosity: CompactStats , libDirs: [] , strict: false - , cwd: "" } defaultParseOptions :: ParseOptions diff --git a/spaghetto/src/Spago/Psa/Output.purs b/spaghetto/src/Spago/Psa/Output.purs index 32815f30b..521c76e6c 100644 --- a/spaghetto/src/Spago/Psa/Output.purs +++ b/spaghetto/src/Spago/Psa/Output.purs @@ -23,6 +23,7 @@ import Data.String as Str import Data.Tuple (Tuple(..)) import Foreign.Object as FO import Node.Path as Path +import Spago.Paths as Paths import Spago.Psa.Types (PsaOutputOptions, PsaError, PsaAnnotedError, PsaPath(..), PsaResult, Position, Filename, Lines, compareByLocation) data ErrorTag = Error | Warning @@ -90,7 +91,7 @@ buildOutput loadLines options result = do let path | Path.isAbsolute f = f - | otherwise = Path.concat [ options.cwd, f ] + | otherwise = Path.concat [ Paths.cwd, f ] in Tuple (errorPath options.libDirs path f) x _ -> Tuple Unknown x diff --git a/spaghetto/src/Spago/Psa/Types.purs b/spaghetto/src/Spago/Psa/Types.purs index 6a57a6dff..e676b63e8 100644 --- a/spaghetto/src/Spago/Psa/Types.purs +++ b/spaghetto/src/Spago/Psa/Types.purs @@ -62,7 +62,6 @@ type PsaOutputOptions = , statVerbosity :: StatVerbosity , libDirs :: Array String , strict :: Boolean - , cwd :: String } type PsaResult = From e21613bba6a7993566c0242539535d3e41b753e2 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Sat, 1 Apr 2023 06:31:59 -0500 Subject: [PATCH 28/78] Use 1 arg for whether to stash & location --- spaghetto/src/Spago/Psa.purs | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index 69df73675..b6bc515cf 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -45,8 +45,7 @@ defaultOptions = defaultParseOptions :: ParseOptions defaultParseOptions = { showSource: true - , stash: false - , stashFile: ".psa-stash" + , stashFile: Nothing -- ".psa-stash" , jsonErrors: false , opts: defaultOptions } @@ -54,8 +53,7 @@ defaultParseOptions = type ParseOptions = { opts :: PsaOutputOptions , showSource :: Boolean - , stash :: Boolean - , stashFile :: String + , stashFile :: Maybe String , jsonErrors :: Boolean } @@ -66,9 +64,6 @@ parseOptions args = Array.foldM parse defaultParseOptions args where parse p arg - | arg == "--stash" = - pure p { stash = true } - | arg == "--json-errors" = pure p { jsonErrors = true } @@ -106,7 +101,7 @@ parseOptions args = pure p { opts = p.opts { libDirs = Array.snoc p.opts.libDirs (Str.drop 9 arg) } } | isPrefix "--stash=" arg = - pure p { stash = true, stashFile = Str.drop 8 arg } + pure p { stashFile = Just $ Str.drop 8 arg } | otherwise = pure p @@ -122,10 +117,10 @@ psaCompile globs pursArgs libDirs = psaCompile' globs pursArgs } psaCompile' :: forall a. Set.Set FilePath -> Array String -> ParseOptions -> Spago (Purs.PursEnv a) Unit -psaCompile' globs pursArgs { opts, showSource, stash, stashFile, jsonErrors } = do - stashData <- - if stash then readStashFile stashFile - else emptyStash +psaCompile' globs pursArgs { opts, showSource, stashFile, jsonErrors } = do + stashData <- case stashFile of + Just f -> readStashFile f + Nothing -> emptyStash result <- Purs.compile globs (Array.snoc pursArgs "--json-errors") let @@ -148,7 +143,7 @@ psaCompile' globs pursArgs { opts, showSource, stash, stashFile, jsonErrors } = loadLinesImpl = if showSource then loadLines files else loadNothing filenames = insertFilenames (insertFilenames Set.empty out.errors) out.warnings merged <- mergeWarnings filenames stashData.date stashData.stash out.warnings - when stash $ writeStashFile stashFile merged + for_ stashFile \f -> writeStashFile f merged out' <- buildOutput loadLinesImpl opts out { warnings = merged } @@ -262,7 +257,6 @@ Available options: --no-colors Disable ANSI colors --no-source Disable original source code printing --strict Promotes src warnings to errors - --stash Enable persistent warnings (defaults to .psa-stash) --stash=FILE Enable persistent warnings using a specific stash file --is-lib=DIR Distinguishing library path (defaults to 'bower_components') From 7d281edf18eb7b5396897c5300a74f441fe0c9bf Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Fri, 31 Mar 2023 16:37:12 -0500 Subject: [PATCH 29/78] Move StatVerbosity into core config --- spaghetto/core/src/Config.purs | 25 ++++++++++++++++++++ spaghetto/src/Spago/Psa.purs | 9 +++---- spaghetto/src/Spago/Psa/Printer/Default.purs | 9 +++---- spaghetto/src/Spago/Psa/Types.purs | 6 ++--- 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/spaghetto/core/src/Config.purs b/spaghetto/core/src/Config.purs index 539c3c11a..43fca6e04 100644 --- a/spaghetto/core/src/Config.purs +++ b/spaghetto/core/src/Config.purs @@ -1,6 +1,7 @@ module Spago.Core.Config ( BackendConfig , BuildOptionsInput + , StatVerbosity(..) , BundleConfig , BundlePlatform(..) , BundleType(..) @@ -70,6 +71,30 @@ type PackageConfig = , publish :: Maybe PublishConfig } +data StatVerbosity + = NoStats + | CompactStats + | VerboseStats + +instance Show StatVerbosity where + show = case _ of + NoStats -> "NoStats" + CompactStats -> "CompactStats" + VerboseStats -> "VerboseStats" + +statVerbosityCodec :: JsonCodec StatVerbosity +statVerbosityCodec = CA.Sum.enumSum print parse + where + print = case _ of + NoStats -> "no-stats" + CompactStats -> "compact-stats" + VerboseStats -> "verbose-stats" + parse = case _ of + "no-stats" -> Just NoStats + "compact-stats" -> Just CompactStats + "verbose-stats" -> Just VerboseStats + _ -> Nothing + packageConfigCodec :: JsonCodec PackageConfig packageConfigCodec = CAR.object "PackageConfig" { name: PackageName.codec diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index b6bc515cf..f00711772 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -23,8 +23,9 @@ import Foreign.Object as FO import Node.Encoding as Encoding import Node.FS.Stats as Stats import Node.FS.Aff as FSA +import Spago.Core.Config as Core import Spago.Purs as Purs -import Spago.Psa.Types (PsaOutputOptions, StatVerbosity(..), psaResultCodec, psaErrorCodec) +import Spago.Psa.Types (PsaOutputOptions, psaResultCodec, psaErrorCodec) import Spago.Psa.Output (buildOutput) import Spago.Psa.Printer.Default as DefaultPrinter import Spago.Psa.Printer.Json as JsonPrinter @@ -37,7 +38,7 @@ defaultOptions = , censorSrc: false , censorCodes: Set.empty , filterCodes: Set.empty - , statVerbosity: CompactStats + , statVerbosity: Core.CompactStats , libDirs: [] , strict: false } @@ -74,10 +75,10 @@ parseOptions args = pure p { opts = p.opts { ansi = false } } | arg == "--verbose-stats" = - pure p { opts = p.opts { statVerbosity = VerboseStats } } + pure p { opts = p.opts { statVerbosity = Core.VerboseStats } } | arg == "--censor-stats" = - pure p { opts = p.opts { statVerbosity = NoStats } } + pure p { opts = p.opts { statVerbosity = Core.NoStats } } | arg == "--strict" = pure p { opts = p.opts { strict = true } } diff --git a/spaghetto/src/Spago/Psa/Printer/Default.purs b/spaghetto/src/Spago/Psa/Printer/Default.purs index 5865d6d30..2d2ffe443 100644 --- a/spaghetto/src/Spago/Psa/Printer/Default.purs +++ b/spaghetto/src/Spago/Psa/Printer/Default.purs @@ -29,8 +29,9 @@ import Dodo.Ansi as DA import Effect (Effect) import Effect.Console as Console import Foreign.Object as FO +import Spago.Core.Config as Core import Spago.Psa.Output (OutputStats, Output) -import Spago.Psa.Types (Lines, Position, PsaAnnotedError, PsaOutputOptions, PsaPath(..), StatVerbosity(..)) +import Spago.Psa.Types (Lines, Position, PsaAnnotedError, PsaOutputOptions, PsaPath(..)) -- | Prints output to the console. print :: PsaOutputOptions -> Output -> Effect Unit @@ -52,9 +53,9 @@ print options output = do lenWarnings = Array.length output.warnings lenErrors = Array.length output.errors renderStats' = case options.statVerbosity of - NoStats -> mempty - CompactStats -> renderStats - VerboseStats -> renderVerboseStats + Core.NoStats -> mempty + Core.CompactStats -> renderStats + Core.VerboseStats -> renderVerboseStats renderWarning :: Int -> Int -> PsaAnnotedError -> D.Doc Ansi.GraphicsParam renderWarning = renderWrapper Ansi.Yellow diff --git a/spaghetto/src/Spago/Psa/Types.purs b/spaghetto/src/Spago/Psa/Types.purs index e676b63e8..840f1ce59 100644 --- a/spaghetto/src/Spago/Psa/Types.purs +++ b/spaghetto/src/Spago/Psa/Types.purs @@ -8,7 +8,6 @@ module Spago.Psa.Types ( ErrorCode , ModuleName , Filename - , StatVerbosity(..) , PsaOutputOptions , PsaResult , PsaError @@ -31,14 +30,13 @@ import Data.Codec.Argonaut.Compat as CACompat import Data.Maybe (Maybe(..)) import Data.Set (Set) import Data.Tuple (Tuple(..)) +import Spago.Core.Config as Core type ErrorCode = String type ModuleName = String type Filename = String type Lines = Array String -data StatVerbosity = NoStats | CompactStats | VerboseStats - -- | Relative files paths from the cwd, tagged as either being part of the -- | source files or library files of a project. The `Unknown` variant exists -- | because some psc errors are inter-module and aren't reported with a @@ -59,7 +57,7 @@ type PsaOutputOptions = , censorSrc :: Boolean , censorCodes :: Set ErrorCode , filterCodes :: Set ErrorCode - , statVerbosity :: StatVerbosity + , statVerbosity :: Core.StatVerbosity , libDirs :: Array String , strict :: Boolean } From f72b7304f0a276c274f44440abb636f99b939d1f Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Fri, 31 Mar 2023 16:48:57 -0500 Subject: [PATCH 30/78] Add but don't yet use psa CLI flags --- spaghetto/bin/src/Flags.purs | 69 ++++++++++++++++++++++++++++++- spaghetto/src/Spago/Psa.purs | 79 ------------------------------------ 2 files changed, 68 insertions(+), 80 deletions(-) diff --git a/spaghetto/bin/src/Flags.purs b/spaghetto/bin/src/Flags.purs index 5c42f0343..068eba416 100644 --- a/spaghetto/bin/src/Flags.purs +++ b/spaghetto/bin/src/Flags.purs @@ -4,6 +4,10 @@ import Spago.Prelude import ArgParse.Basic (ArgParser) import ArgParse.Basic as ArgParser +import Data.String as String +import Spago.Core.Config as Core +import Data.Set (Set) +import Data.Set as Set selectedPackage ∷ ArgParser (Maybe String) selectedPackage = @@ -11,6 +15,69 @@ selectedPackage = "Select the local project to build" # ArgParser.optional +psaStrict ∷ ArgParser Boolean +psaStrict = + ArgParser.flag [ "--strict" ] + "Promotes project sources' warnings to errors" + # ArgParser.boolean + +psaCensorWarnings ∷ ArgParser Boolean +psaCensorWarnings = + ArgParser.flag [ "--psa-censor-warnings" ] + "Censor all warnings" + # ArgParser.boolean + +psaCensorLib ∷ ArgParser Boolean +psaCensorLib = + ArgParser.flag [ "--psa-censor-lib" ] + "Censor warnings from library sources" + # ArgParser.boolean + +psaCensorSrc ∷ ArgParser Boolean +psaCensorSrc = + ArgParser.flag [ "--psa-censor-src" ] + "Censor warnings from project sources" + # ArgParser.boolean + +psaShowSource ∷ ArgParser Boolean +psaShowSource = + ArgParser.flag [ "--psa-no-source" ] + "Disable original source code printing" + # ArgParser.boolean + +psaCensorCodes :: ArgParser (Set String) +psaCensorCodes = + ArgParser.argument [ "--psa-censor-codes" ] + "Censor specific error codes (comma-separated list)" + # ArgParser.unformat "CODE1,CODE2,...,CODEX" (Right <<< foldMap Set.singleton <<< String.split (String.Pattern ",")) + # ArgParser.default Set.empty + +psaFilterCodes :: ArgParser (Set String) +psaFilterCodes = + ArgParser.argument [ "--psa-filter-codes" ] + "Only show specific error codes (comma-separated list)" + # ArgParser.unformat "CODE1,CODE2,...,CODEX" (Right <<< foldMap Set.singleton <<< String.split (String.Pattern ",")) + # ArgParser.default Set.empty + +psaStatVerbosity :: ArgParser Core.StatVerbosity +psaStatVerbosity = ArgParser.choose "StatVerbosity" + [ Core.VerboseStats <$ ArgParser.flag [ "--psa-verbose-stats" ] "Show counts for each warning type" + , ArgParser.default Core.CompactStats $ Core.NoStats <$ ArgParser.flag [ "--psa-censor-stats" ] "Censor warning/error summary" + ] + +psaStashFile ∷ ArgParser (Either Boolean String) +psaStashFile = ArgParser.choose "stash" + [ ArgParser.argument [ "--psa-stash" ] "Enable persistent warnings using a specific stash file" + # ArgParser.unformat "FILE" (Right <<< Right) + , ArgParser.default (Left false) $ (Left true) <$ ArgParser.flag [ "--psa-stash" ] "Enable persistent warnings using default stash file location" + ] + +jsonErrors ∷ ArgParser Boolean +jsonErrors = + ArgParser.flag [ "--json-errors" ] + "Output compiler warnings/errors as JSON" + # ArgParser.boolean + minify ∷ ArgParser Boolean minify = ArgParser.flag [ "--minify" ] @@ -63,7 +130,7 @@ verbose = noColor ∷ ArgParser Boolean noColor = - ArgParser.flag [ "--no-color" ] + ArgParser.flag [ "--no-color", "--monochrome" ] "Force logging without ANSI color escape sequences" # ArgParser.boolean # ArgParser.default false diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index f00711772..5270f60e6 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -58,59 +58,6 @@ type ParseOptions = , jsonErrors :: Boolean } -parseOptions - :: Array String - -> Effect ParseOptions -parseOptions args = - Array.foldM parse defaultParseOptions args - where - parse p arg - | arg == "--json-errors" = - pure p { jsonErrors = true } - - | arg == "--no-source" = - pure p { showSource = false } - - | arg == "--no-colors" || arg == "--monochrome" = - pure p { opts = p.opts { ansi = false } } - - | arg == "--verbose-stats" = - pure p { opts = p.opts { statVerbosity = Core.VerboseStats } } - - | arg == "--censor-stats" = - pure p { opts = p.opts { statVerbosity = Core.NoStats } } - - | arg == "--strict" = - pure p { opts = p.opts { strict = true } } - - | arg == "--censor-warnings" = - pure p { opts = p.opts { censorWarnings = true } } - - | arg == "--censor-lib" = - pure p { opts = p.opts { censorLib = true } } - - | arg == "--censor-src" = - pure p { opts = p.opts { censorSrc = true } } - - | isPrefix "--censor-codes=" arg = - pure p { opts = p.opts { censorCodes = foldr Set.insert p.opts.censorCodes (Str.split (Str.Pattern ",") (Str.drop 15 arg)) } } - - | isPrefix "--filter-codes=" arg = - pure p { opts = p.opts { filterCodes = foldr Set.insert p.opts.filterCodes (Str.split (Str.Pattern ",") (Str.drop 15 arg)) } } - - | isPrefix "--is-lib=" arg = - pure p { opts = p.opts { libDirs = Array.snoc p.opts.libDirs (Str.drop 9 arg) } } - - | isPrefix "--stash=" arg = - pure p { stashFile = Just $ Str.drop 8 arg } - - | otherwise = pure p - - isPrefix s str = - case Str.indexOf (Str.Pattern s) str of - Just x | x == 0 -> true - _ -> false - psaCompile :: forall a. Set.Set FilePath -> Array String -> Array String -> Spago (Purs.PursEnv a) Unit psaCompile globs pursArgs libDirs = psaCompile' globs pursArgs $ defaultParseOptions @@ -237,29 +184,3 @@ psaCompile' globs pursArgs { opts, showSource, stashFile, jsonErrors } = do _ <- liftEffect $ Ref.modify_ (FO.insert f s') fileStat pure s' pure $ old' <> new - -usage :: String -usage = - """psa - Error/Warning reporting frontend for 'purs compile' - -Usage: psa [--censor-lib] [--censor-src] - [--censor-codes=CODES] [--filter-codes=CODES] - [--no-colors] [--no-source] - [--is-lib=DIR] [--purs=PURS] [--stash] - -Available options: - --verbose-stats Show counts for each warning type - --censor-stats Censor warning/error summary - --censor-warnings Censor all warnings - --censor-lib Censor warnings from library sources - --censor-src Censor warnings from project sources - --censor-codes=CODES Censor specific error codes - --filter-codes=CODES Only show specific error codes - --no-colors Disable ANSI colors - --no-source Disable original source code printing - --strict Promotes src warnings to errors - --stash=FILE Enable persistent warnings using a specific stash file - --is-lib=DIR Distinguishing library path (defaults to 'bower_components') - - CODES Comma-separated list of purs error codes -""" From 68536c3103293d4f50797579f36df8fb09892918 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Sat, 1 Apr 2023 06:52:25 -0500 Subject: [PATCH 31/78] Refactor psaCompile options Psa config values that are configured primarily via the CLI or which are calculated in Build.purs are passed in separately from the PsaOptions value, which correlates to what is stored in the Spago config file --- spaghetto/src/Spago/Command/Build.purs | 11 ++- spaghetto/src/Spago/Psa.purs | 70 ++++++++++++-------- spaghetto/src/Spago/Psa/Output.purs | 2 +- spaghetto/src/Spago/Psa/Printer/Default.purs | 2 +- spaghetto/src/Spago/Psa/Types.purs | 4 +- 5 files changed, 54 insertions(+), 35 deletions(-) diff --git a/spaghetto/src/Spago/Command/Build.purs b/spaghetto/src/Spago/Command/Build.purs index 9b3c54c92..6930d69fb 100644 --- a/spaghetto/src/Spago/Command/Build.purs +++ b/spaghetto/src/Spago/Command/Build.purs @@ -35,7 +35,7 @@ type BuildOptions = run :: forall a. BuildOptions -> Spago (BuildEnv a) Unit run opts = do logInfo "Building..." - { dependencies, workspace } <- ask + { dependencies, workspace, logOptions } <- ask let -- depsOnly means "no packages from the monorepo", so we filter out the workspace packages Tuple dependencyLibs dependencyGlobs = Array.unzip $ (Tuple.uncurry $ Config.sourceGlob' WithTestGlobs) =<< case opts.depsOnly of @@ -77,10 +77,15 @@ run opts = do ] let + psaArgs = + { libraryDirs: dependencyLibs + , color: logOptions.color + , jsonErrors: false + } buildBackend globs = do case workspace.backend of Nothing -> - Psa.psaCompile globs (addOutputArgs opts.pursArgs) dependencyLibs + Psa.psaCompile globs (addOutputArgs opts.pursArgs) psaArgs Just backend -> do when (isJust $ Cmd.findFlag { flags: [ "-g", "--codegen" ], args: opts.pursArgs }) do die @@ -89,7 +94,7 @@ run opts = do , "Remove the argument to solve the error" ] let args = (addOutputArgs opts.pursArgs) <> [ "--codegen", "corefn" ] - Psa.psaCompile globs args dependencyLibs + Psa.psaCompile globs args psaArgs logInfo $ "Compiling with backend \"" <> backend.cmd <> "\"" logDebug $ "Running command `" <> backend.cmd <> "`" diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index 5270f60e6..cd535658d 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -15,57 +15,71 @@ import Data.Codec.Argonaut as CA import Data.DateTime.Instant (toDateTime) import Data.Foldable (foldr) import Data.Set as Set -import Effect.Exception as Exception import Data.String as Str +import Effect.Exception as Exception import Effect.Now (now) import Effect.Ref as Ref import Foreign.Object as FO import Node.Encoding as Encoding -import Node.FS.Stats as Stats import Node.FS.Aff as FSA +import Node.FS.Stats as Stats import Spago.Core.Config as Core -import Spago.Purs as Purs -import Spago.Psa.Types (PsaOutputOptions, psaResultCodec, psaErrorCodec) import Spago.Psa.Output (buildOutput) import Spago.Psa.Printer.Default as DefaultPrinter import Spago.Psa.Printer.Json as JsonPrinter +import Spago.Psa.Types (PsaOutputOptions, ErrorCode, psaErrorCodec, psaResultCodec) +import Spago.Purs as Purs + +type PsaArgs = + { libraryDirs :: Array String + , jsonErrors :: Boolean + , color :: Boolean + } -defaultOptions :: PsaOutputOptions -defaultOptions = - { ansi: true +defaultParseOptions :: PsaOptions +defaultParseOptions = + { showSource: true + , stashFile: Nothing -- ".psa-stash" , censorWarnings: false , censorLib: false , censorSrc: false , censorCodes: Set.empty , filterCodes: Set.empty , statVerbosity: Core.CompactStats - , libDirs: [] , strict: false } -defaultParseOptions :: ParseOptions -defaultParseOptions = - { showSource: true - , stashFile: Nothing -- ".psa-stash" - , jsonErrors: false - , opts: defaultOptions +type PsaOptions = + { showSource :: Boolean + , stashFile :: Maybe String + , censorWarnings :: Boolean + , censorLib :: Boolean + , censorSrc :: Boolean + , censorCodes :: Set ErrorCode + , filterCodes :: Set ErrorCode + , statVerbosity :: Core.StatVerbosity + , strict :: Boolean } -type ParseOptions = - { opts :: PsaOutputOptions - , showSource :: Boolean - , stashFile :: Maybe String - , jsonErrors :: Boolean +toOutputOptions :: PsaArgs -> PsaOptions -> PsaOutputOptions +toOutputOptions { libraryDirs, color } options = + { color + , censorWarnings: options.censorWarnings + , censorLib: options.censorLib + , censorSrc: options.censorSrc + , censorCodes: options.censorCodes + , filterCodes: options.filterCodes + , statVerbosity: options.statVerbosity + , libraryDirs + , strict: options.strict } -psaCompile :: forall a. Set.Set FilePath -> Array String -> Array String -> Spago (Purs.PursEnv a) Unit -psaCompile globs pursArgs libDirs = psaCompile' globs pursArgs - $ defaultParseOptions - { opts = defaultParseOptions.opts { libDirs = libDirs } - } +psaCompile :: forall a. Set.Set FilePath -> Array String -> PsaArgs -> Spago (Purs.PursEnv a) Unit +psaCompile globs pursArgs psaArgs = psaCompile' globs pursArgs psaArgs defaultParseOptions -psaCompile' :: forall a. Set.Set FilePath -> Array String -> ParseOptions -> Spago (Purs.PursEnv a) Unit -psaCompile' globs pursArgs { opts, showSource, stashFile, jsonErrors } = do +psaCompile' :: forall a. Set.Set FilePath -> Array String -> PsaArgs -> PsaOptions -> Spago (Purs.PursEnv a) Unit +psaCompile' globs pursArgs psaArgs options@{ showSource, stashFile } = do + let outputOptions = toOutputOptions psaArgs options stashData <- case stashFile of Just f -> readStashFile f Nothing -> emptyStash @@ -93,9 +107,9 @@ psaCompile' globs pursArgs { opts, showSource, stashFile, jsonErrors } = do merged <- mergeWarnings filenames stashData.date stashData.stash out.warnings for_ stashFile \f -> writeStashFile f merged - out' <- buildOutput loadLinesImpl opts out { warnings = merged } + out' <- buildOutput loadLinesImpl outputOptions out { warnings = merged } - liftEffect $ if jsonErrors then JsonPrinter.print out' else DefaultPrinter.print opts out' + liftEffect $ if psaArgs.jsonErrors then JsonPrinter.print out' else DefaultPrinter.print outputOptions out' pure $ FO.isEmpty out'.stats.allErrors diff --git a/spaghetto/src/Spago/Psa/Output.purs b/spaghetto/src/Spago/Psa/Output.purs index 521c76e6c..df95b1bd8 100644 --- a/spaghetto/src/Spago/Psa/Output.purs +++ b/spaghetto/src/Spago/Psa/Output.purs @@ -93,7 +93,7 @@ buildOutput loadLines options result = do | Path.isAbsolute f = f | otherwise = Path.concat [ Paths.cwd, f ] in - Tuple (errorPath options.libDirs path f) x + Tuple (errorPath options.libraryDirs path f) x _ -> Tuple Unknown x onError :: ErrorTag -> Output -> Tuple PsaPath PsaError -> m Output diff --git a/spaghetto/src/Spago/Psa/Printer/Default.purs b/spaghetto/src/Spago/Psa/Printer/Default.purs index 2d2ffe443..cede1d4e6 100644 --- a/spaghetto/src/Spago/Psa/Printer/Default.purs +++ b/spaghetto/src/Spago/Psa/Printer/Default.purs @@ -48,7 +48,7 @@ print options output = do where printDoc - | options.ansi = D.print DA.ansiGraphics D.twoSpaces + | options.color = D.print DA.ansiGraphics D.twoSpaces | otherwise = D.print D.plainText D.twoSpaces lenWarnings = Array.length output.warnings lenErrors = Array.length output.errors diff --git a/spaghetto/src/Spago/Psa/Types.purs b/spaghetto/src/Spago/Psa/Types.purs index 840f1ce59..d9eea0748 100644 --- a/spaghetto/src/Spago/Psa/Types.purs +++ b/spaghetto/src/Spago/Psa/Types.purs @@ -51,14 +51,14 @@ derive instance Eq PsaPath derive instance Ord PsaPath type PsaOutputOptions = - { ansi :: Boolean + { color :: Boolean , censorWarnings :: Boolean , censorLib :: Boolean , censorSrc :: Boolean , censorCodes :: Set ErrorCode , filterCodes :: Set ErrorCode , statVerbosity :: Core.StatVerbosity - , libDirs :: Array String + , libraryDirs :: Array String , strict :: Boolean } From c5426ffb83c6c9a76cad403647e9336d4b61288d Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Sat, 1 Apr 2023 06:54:45 -0500 Subject: [PATCH 32/78] Add new flags to corresponding envs --- spaghetto/bin/src/Main.purs | 46 +++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/spaghetto/bin/src/Main.purs b/spaghetto/bin/src/Main.purs index a691f029d..36b5737fd 100644 --- a/spaghetto/bin/src/Main.purs +++ b/spaghetto/bin/src/Main.purs @@ -34,6 +34,7 @@ import Spago.Command.Registry as Registry import Spago.Command.Run as Run import Spago.Command.Sources as Sources import Spago.Command.Test as Test +import Spago.Core.Config as Core import Spago.Config (BundleConfig, BundlePlatform(..), BundleType(..), Package, RunConfig, TestConfig) import Spago.Config as Config import Spago.FS as FS @@ -68,6 +69,20 @@ type InstallArgs = , output :: Maybe String , pedanticPackages :: Boolean , ensureRanges :: Boolean + , jsonErrors :: Boolean + , psaArgs :: PsaArgs + } + +type PsaArgs = + { strict :: Boolean + , censorWarnings :: Boolean + , censorLib :: Boolean + , censorSrc :: Boolean + , showSource :: Boolean + , censorCodes :: Set String + , filterCodes :: Set String + , statVerbosity :: Core.StatVerbosity + , stashFile :: Either Boolean String } type BuildArgs a = @@ -77,6 +92,8 @@ type BuildArgs a = , output :: Maybe String , pedanticPackages :: Boolean , ensureRanges :: Boolean + , jsonErrors :: Boolean + , psaArgs :: PsaArgs | a } @@ -96,6 +113,8 @@ type RunArgs = , execArgs :: Maybe (Array String) , main :: Maybe String , ensureRanges :: Boolean + , jsonErrors :: Boolean + , psaArgs :: PsaArgs } type TestArgs = @@ -105,6 +124,8 @@ type TestArgs = , pursArgs :: List String , backendArgs :: List String , execArgs :: Maybe (Array String) + , jsonErrors :: Boolean + , psaArgs :: PsaArgs } type SourcesArgs = @@ -133,6 +154,8 @@ type BundleArgs = , pedanticPackages :: Boolean , type :: Maybe String , ensureRanges :: Boolean + , jsonErrors :: Boolean + , psaArgs :: PsaArgs } type PublishArgs = @@ -273,8 +296,23 @@ installArgsParser = , output: Flags.output , pedanticPackages: Flags.pedanticPackages , ensureRanges: Flags.ensureRanges + , jsonErrors: Flags.jsonErrors + , psaArgs: psaArgsParser } +psaArgsParser :: ArgParser PsaArgs +psaArgsParser = ArgParser.fromRecord + { strict: Flags.psaStrict + , censorWarnings: Flags.psaCensorWarnings + , censorLib: Flags.psaCensorLib + , censorSrc: Flags.psaCensorSrc + , showSource: Flags.psaShowSource + , censorCodes: Flags.psaCensorCodes + , filterCodes: Flags.psaFilterCodes + , statVerbosity: Flags.psaStatVerbosity + , stashFile: Flags.psaStashFile + } + buildArgsParser :: ArgParser (BuildArgs ()) buildArgsParser = ArgParser.fromRecord { selectedPackage: Flags.selectedPackage @@ -283,6 +321,8 @@ buildArgsParser = ArgParser.fromRecord , output: Flags.output , pedanticPackages: Flags.pedanticPackages , ensureRanges: Flags.ensureRanges + , jsonErrors: Flags.jsonErrors + , psaArgs: psaArgsParser } replArgsParser :: ArgParser ReplArgs @@ -302,6 +342,8 @@ runArgsParser = ArgParser.fromRecord , pedanticPackages: Flags.pedanticPackages , main: Flags.moduleName , ensureRanges: Flags.ensureRanges + , jsonErrors: Flags.jsonErrors + , psaArgs: psaArgsParser } testArgsParser :: ArgParser TestArgs @@ -312,6 +354,8 @@ testArgsParser = ArgParser.fromRecord , execArgs: Flags.execArgs , output: Flags.output , pedanticPackages: Flags.pedanticPackages + , jsonErrors: Flags.jsonErrors + , psaArgs: psaArgsParser } bundleArgsParser :: ArgParser BundleArgs @@ -328,6 +372,8 @@ bundleArgsParser = , output: Flags.output , pedanticPackages: Flags.pedanticPackages , ensureRanges: Flags.ensureRanges + , jsonErrors: Flags.jsonErrors + , psaArgs: psaArgsParser } publishArgsParser :: ArgParser PublishArgs From b9de0d5b6ef5b4b838b8bb8fa1fb886c6a2d1344 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Sat, 1 Apr 2023 09:40:26 -0500 Subject: [PATCH 33/78] 99% there but compiler errors are incomprehensible --- spaghetto/bin/src/Flags.purs | 66 ++++++++++++--------- spaghetto/bin/src/Main.purs | 57 ++++++++++++------ spaghetto/core/src/Config.purs | 73 ++++++++++++++++++++++++ spaghetto/src/Spago/Command/Build.purs | 33 +++++++++-- spaghetto/src/Spago/Command/Init.purs | 2 + spaghetto/src/Spago/Command/Publish.purs | 3 +- spaghetto/src/Spago/Config.purs | 2 + spaghetto/src/Spago/Paths.purs | 6 ++ spaghetto/src/Spago/Psa.purs | 13 ++--- 9 files changed, 200 insertions(+), 55 deletions(-) diff --git a/spaghetto/bin/src/Flags.purs b/spaghetto/bin/src/Flags.purs index 068eba416..8b9eec70e 100644 --- a/spaghetto/bin/src/Flags.purs +++ b/spaghetto/bin/src/Flags.purs @@ -4,10 +4,12 @@ import Spago.Prelude import ArgParse.Basic (ArgParser) import ArgParse.Basic as ArgParser +import Data.Array.NonEmpty as NEA +import Data.Set.NonEmpty (NonEmptySet) +import Data.Set.NonEmpty as NonEmptySet import Data.String as String +import Spago.Core.Config (ShowSourceCode(..)) import Spago.Core.Config as Core -import Data.Set (Set) -import Data.Set as Set selectedPackage ∷ ArgParser (Maybe String) selectedPackage = @@ -15,61 +17,73 @@ selectedPackage = "Select the local project to build" # ArgParser.optional -psaStrict ∷ ArgParser Boolean +configBoolean' :: Boolean -> ArgParser Unit -> ArgParser (Maybe Boolean) +configBoolean' b p = ArgParser.default (Just b) $ Just (not b) <$ p + +configBooleanTrue :: ArgParser Unit -> ArgParser (Maybe Boolean) +configBooleanTrue = configBoolean' true + +configBooleanFalse :: ArgParser Unit -> ArgParser (Maybe Boolean) +configBooleanFalse = configBoolean' false + +psaStrict ∷ ArgParser (Maybe Boolean) psaStrict = ArgParser.flag [ "--strict" ] "Promotes project sources' warnings to errors" - # ArgParser.boolean + # configBooleanFalse -psaCensorWarnings ∷ ArgParser Boolean +psaCensorWarnings ∷ ArgParser (Maybe Boolean) psaCensorWarnings = ArgParser.flag [ "--psa-censor-warnings" ] "Censor all warnings" - # ArgParser.boolean + # configBooleanFalse -psaCensorLib ∷ ArgParser Boolean +psaCensorLib ∷ ArgParser (Maybe Boolean) psaCensorLib = ArgParser.flag [ "--psa-censor-lib" ] "Censor warnings from library sources" - # ArgParser.boolean + # configBooleanFalse -psaCensorSrc ∷ ArgParser Boolean +psaCensorSrc ∷ ArgParser (Maybe Boolean) psaCensorSrc = ArgParser.flag [ "--psa-censor-src" ] "Censor warnings from project sources" - # ArgParser.boolean + # configBooleanFalse -psaShowSource ∷ ArgParser Boolean +psaShowSource ∷ ArgParser (Maybe ShowSourceCode) psaShowSource = - ArgParser.flag [ "--psa-no-source" ] - "Disable original source code printing" - # ArgParser.boolean + NoSourceCode + <$ ArgParser.flag [ "--psa-no-source" ] + "Disable original source code printing" + # ArgParser.optional -psaCensorCodes :: ArgParser (Set String) +psaCensorCodes :: ArgParser (Maybe (NonEmptySet String)) psaCensorCodes = ArgParser.argument [ "--psa-censor-codes" ] "Censor specific error codes (comma-separated list)" - # ArgParser.unformat "CODE1,CODE2,...,CODEX" (Right <<< foldMap Set.singleton <<< String.split (String.Pattern ",")) - # ArgParser.default Set.empty + # ArgParser.unformat "CODE1,CODE2,...,CODEX" + (maybe (Left "Did not get a set of values") (Right <<< NonEmptySet.fromFoldable1) <<< NEA.fromArray <<< String.split (String.Pattern ",")) + # ArgParser.optional -psaFilterCodes :: ArgParser (Set String) +psaFilterCodes :: ArgParser (Maybe (NonEmptySet String)) psaFilterCodes = ArgParser.argument [ "--psa-filter-codes" ] "Only show specific error codes (comma-separated list)" - # ArgParser.unformat "CODE1,CODE2,...,CODEX" (Right <<< foldMap Set.singleton <<< String.split (String.Pattern ",")) - # ArgParser.default Set.empty + # ArgParser.unformat "CODE1,CODE2,...,CODEX" + (maybe (Left "Did not get a set of values") (Right <<< NonEmptySet.fromFoldable1) <<< NEA.fromArray <<< String.split (String.Pattern ",")) + # ArgParser.optional -psaStatVerbosity :: ArgParser Core.StatVerbosity -psaStatVerbosity = ArgParser.choose "StatVerbosity" +psaStatVerbosity :: ArgParser (Maybe Core.StatVerbosity) +psaStatVerbosity = ArgParser.optional $ ArgParser.choose "StatVerbosity" [ Core.VerboseStats <$ ArgParser.flag [ "--psa-verbose-stats" ] "Show counts for each warning type" - , ArgParser.default Core.CompactStats $ Core.NoStats <$ ArgParser.flag [ "--psa-censor-stats" ] "Censor warning/error summary" + , Core.NoStats <$ ArgParser.flag [ "--psa-censor-stats" ] "Censor warning/error summary" ] -psaStashFile ∷ ArgParser (Either Boolean String) -psaStashFile = ArgParser.choose "stash" +psaStashFile ∷ ArgParser (Maybe (Either Boolean String)) +psaStashFile = ArgParser.optional $ ArgParser.choose "stash" [ ArgParser.argument [ "--psa-stash" ] "Enable persistent warnings using a specific stash file" # ArgParser.unformat "FILE" (Right <<< Right) - , ArgParser.default (Left false) $ (Left true) <$ ArgParser.flag [ "--psa-stash" ] "Enable persistent warnings using default stash file location" + , Left true <$ ArgParser.flag [ "--psa-stash" ] "Enable persistent warnings using default stash file location" ] jsonErrors ∷ ArgParser Boolean diff --git a/spaghetto/bin/src/Main.purs b/spaghetto/bin/src/Main.purs index 36b5737fd..c8df36f8a 100644 --- a/spaghetto/bin/src/Main.purs +++ b/spaghetto/bin/src/Main.purs @@ -4,12 +4,16 @@ import Spago.Prelude import ArgParse.Basic (ArgParser) import ArgParse.Basic as ArgParser +import Control.Alt (alt) import Data.Array as Array import Data.Array.NonEmpty as NonEmptyArray import Data.Codec.Argonaut.Common as CA.Common import Data.JSDate as JSDate import Data.List as List import Data.Map as Map +import Data.Set as Set +import Data.Set.NonEmpty (NonEmptySet) +import Data.Set.NonEmpty as NonEmptySet import Effect.Aff as Aff import Effect.Class.Console as Console import Effect.Ref as Ref @@ -27,21 +31,22 @@ import Spago.Command.Build as Build import Spago.Command.Bundle as Bundle import Spago.Command.Fetch as Fetch import Spago.Command.Init as Init -import Spago.Command.Ls as Ls import Spago.Command.Ls (LsDepsArgs, LsPackagesArgs) +import Spago.Command.Ls as Ls import Spago.Command.Publish as Publish import Spago.Command.Registry as Registry import Spago.Command.Run as Run import Spago.Command.Sources as Sources import Spago.Command.Test as Test -import Spago.Core.Config as Core import Spago.Config (BundleConfig, BundlePlatform(..), BundleType(..), Package, RunConfig, TestConfig) import Spago.Config as Config +import Spago.Core.Config as Core import Spago.FS as FS import Spago.Git as Git import Spago.Json as Json import Spago.Log (LogVerbosity(..)) import Spago.Paths as Paths +import Spago.Psa (PsaOptions) import Spago.Purs as Purs import Unsafe.Coerce (unsafeCoerce) @@ -74,15 +79,15 @@ type InstallArgs = } type PsaArgs = - { strict :: Boolean - , censorWarnings :: Boolean - , censorLib :: Boolean - , censorSrc :: Boolean - , showSource :: Boolean - , censorCodes :: Set String - , filterCodes :: Set String - , statVerbosity :: Core.StatVerbosity - , stashFile :: Either Boolean String + { strict :: Maybe Boolean + , censorWarnings :: Maybe Boolean + , censorLib :: Maybe Boolean + , censorSrc :: Maybe Boolean + , showSource :: Maybe Core.ShowSourceCode + , censorCodes :: Maybe (NonEmptySet String) + , filterCodes :: Maybe (NonEmptySet String) + , statVerbosity :: Maybe Core.StatVerbosity + , stashFile :: Maybe (Either Boolean String) } type BuildArgs a = @@ -465,9 +470,10 @@ main = runSpago buildEnv (Build.run options) Publish { selectedPackage } -> do { env, fetchOpts } <- mkFetchEnv { packages: mempty, selectedPackage, ensureRanges: false } - publishEnv <- runSpago env do - dependencies <- Fetch.run fetchOpts - mkPublishEnv dependencies + -- TODO: --no-fetch flag + dependencies <- runSpago env (Fetch.run fetchOpts) + env' <- runSpago env (mkBuildEnv { depsOnly: false, pursArgs: [] } dependencies) + publishEnv <- runSpago env' (mkPublishEnv dependencies) void $ runSpago publishEnv (Publish.publish {}) Repl args -> do -- TODO implement @@ -679,9 +685,28 @@ mkBuildEnv buildArgs dependencies = do ) workspace.backend } - pure { logOptions, purs, git, dependencies, workspace: newWorkspace } -mkPublishEnv :: forall a. Map PackageName Package -> Spago (Fetch.FetchEnv a) (Publish.PublishEnv a) + psaConfig :: Core.PsaConfig + psaConfig = + { strict: alt buildArgs.psaArgs.strict $ config >>= _.strict + , censorWarnings: alt buildArgs.psaArgs.censorWarnings $ config >>= _.censorWarnings + , censorLib: alt buildArgs.psaArgs.censorWarnings $ config >>= _.censorLib + , censorSrc: alt buildArgs.psaArgs.censorSrc $ config >>= _.censorSrc + , showSource: alt buildArgs.psaArgs.showSource $ config >>= _.showSource + , censorCodes: alt buildArgs.psaArgs.censorCodes $ config >>= _.censorCodes + , filterCodes: alt buildArgs.psaArgs.filterCodes $ config >>= _.filterCodes + , statVerbosity: alt buildArgs.psaArgs.statVerbosity $ config >>= _.statVerbosity + , stashFile: alt buildArgs.psaArgs.stashFile $ config >>= _.stashFile + } + where + config :: Maybe Core.PsaConfig + config = case workspace.selected of + Just p -> p.package.build >>= _.psaOptions + Nothing -> workspace.buildOptions.psaOptions + + pure { logOptions, purs, git, dependencies, workspace: newWorkspace, psaConfig } + +mkPublishEnv :: forall a. Map PackageName Package -> Spago (Build.BuildEnv a) (Publish.PublishEnv a) mkPublishEnv dependencies = do env <- ask purs <- Purs.getPurs diff --git a/spaghetto/core/src/Config.purs b/spaghetto/core/src/Config.purs index 43fca6e04..e880c133e 100644 --- a/spaghetto/core/src/Config.purs +++ b/spaghetto/core/src/Config.purs @@ -1,6 +1,9 @@ module Spago.Core.Config ( BackendConfig , BuildOptionsInput + , BuildConfig + , PsaConfig + , ShowSourceCode(..) , StatVerbosity(..) , BundleConfig , BundlePlatform(..) @@ -34,12 +37,15 @@ module Spago.Core.Config import Spago.Core.Prelude import Data.Codec.Argonaut as CA +import Data.Codec.Argonaut.Common as CA.Common import Data.Codec.Argonaut.Record as CAR import Data.Codec.Argonaut.Sum as CA.Sum import Data.Either as Either import Data.List as List import Data.Map as Map +import Data.Profunctor (dimap) import Data.Profunctor as Profunctor +import Data.Set.NonEmpty as NonEmptySet import Partial.Unsafe (unsafeCrashWith) import Registry.Internal.Codec as Internal.Codec import Registry.License as License @@ -65,12 +71,74 @@ type PackageConfig = { name :: PackageName , description :: Maybe String , dependencies :: Dependencies + , build :: Maybe BuildConfig , bundle :: Maybe BundleConfig , run :: Maybe RunConfig , test :: Maybe TestConfig , publish :: Maybe PublishConfig } +type BuildConfig = + { psaOptions :: Maybe PsaConfig + } + +buildConfigCodec :: JsonCodec BuildConfig +buildConfigCodec = CAR.object "BuildConfig" + { psaOptions: CAR.optional psaConfigCodec + } + +type PsaConfig = + { censorWarnings :: Maybe Boolean + , censorLib :: Maybe Boolean + , censorSrc :: Maybe Boolean + , censorCodes :: Maybe (NonEmptySet.NonEmptySet String) + , filterCodes :: Maybe (NonEmptySet.NonEmptySet String) + , statVerbosity :: Maybe StatVerbosity + , showSource :: Maybe ShowSourceCode + , strict :: Maybe Boolean + , stashFile :: Maybe (Either Boolean String) + } + +psaConfigCodec :: JsonCodec PsaConfig +psaConfigCodec = CAR.object "PsaConfig" + { censorWarnings: CAR.optional CA.boolean + , censorLib: CAR.optional CA.boolean + , censorSrc: CAR.optional CA.boolean + , censorCodes: CAR.optional $ CA.Common.nonEmptySet CA.string + , filterCodes: CAR.optional $ CA.Common.nonEmptySet CA.string + , statVerbosity: CAR.optional statVerbosityCodec + , showSource: CAR.optional showSourceCodec + , strict: CAR.optional CA.boolean + , stashFile: CAR.optional stashFileCodec + } + +stashFileCodec :: JsonCodec (Either Boolean String) +stashFileCodec = CA.Sum.enumSum (either show identity) case _ of + "true" -> Just $ Left true + "false" -> Just $ Left false + x -> Just $ Right x + +data ShowSourceCode + = ShowSourceCode + | NoSourceCode + +derive instance Eq ShowSourceCode + +showSourceCodec :: JsonCodec ShowSourceCode +showSourceCodec = dimap to from CA.boolean + where + to = case _ of + ShowSourceCode -> true + NoSourceCode -> false + from = case _ of + false -> NoSourceCode + true -> ShowSourceCode + +instance Show ShowSourceCode where + show = case _ of + ShowSourceCode -> "ShowSourceCode" + NoSourceCode -> "NoSourceCode" + data StatVerbosity = NoStats | CompactStats @@ -100,6 +168,7 @@ packageConfigCodec = CAR.object "PackageConfig" { name: PackageName.codec , description: CAR.optional CA.string , dependencies: dependenciesCodec + , build: CAR.optional buildConfigCodec , bundle: CAR.optional bundleConfigCodec , run: CAR.optional runConfigCodec , test: CAR.optional testConfigCodec @@ -134,6 +203,7 @@ type TestConfig = { main :: String , execArgs :: Maybe (Array String) , dependencies :: Dependencies + , psaOptions :: Maybe PsaConfig } testConfigCodec :: JsonCodec TestConfig @@ -141,6 +211,7 @@ testConfigCodec = CAR.object "TestConfig" { main: CA.string , execArgs: CAR.optional (CA.array CA.string) , dependencies: dependenciesCodec + , psaOptions: CAR.optional psaConfigCodec } type BackendConfig = @@ -290,12 +361,14 @@ workspaceConfigCodec = CAR.object "WorkspaceConfig" type BuildOptionsInput = { output :: Maybe FilePath , pedantic_packages :: Maybe Boolean + , psaOptions :: Maybe PsaConfig } buildOptionsCodec :: JsonCodec BuildOptionsInput buildOptionsCodec = CAR.object "CompileOptionsInput" { output: CAR.optional CA.string , pedantic_packages: CAR.optional CA.boolean + , psaOptions: CAR.optional psaConfigCodec } data SetAddress diff --git a/spaghetto/src/Spago/Command/Build.purs b/spaghetto/src/Spago/Command/Build.purs index 6930d69fb..287e4722c 100644 --- a/spaghetto/src/Spago/Command/Build.purs +++ b/spaghetto/src/Spago/Command/Build.purs @@ -5,15 +5,20 @@ module Spago.Command.Build import Spago.Prelude +import Control.Alternative as Alternative import Data.Array as Array import Data.Map as Map import Data.Set as Set +import Data.Set.NonEmpty as NonEmptySet import Data.Tuple as Tuple +import Node.Path as Path +import Registry.PackageName as PackageName import Spago.BuildInfo as BuildInfo import Spago.Cmd as Cmd -import Spago.Config (Package(..), WithTestGlobs(..), Workspace, WorkspacePackage) +import Spago.Config (Package(..), WithTestGlobs(..), Workspace, WorkspacePackage, PsaConfig) import Spago.Config as Config import Spago.Git (Git) +import Spago.Paths as Paths import Spago.Psa as Psa import Spago.Purs (Purs) import Spago.Purs.Graph as Graph @@ -24,6 +29,7 @@ type BuildEnv a = , dependencies :: Map PackageName Package , logOptions :: LogOptions , workspace :: Workspace + , psaConfig :: PsaConfig | a } @@ -35,7 +41,7 @@ type BuildOptions = run :: forall a. BuildOptions -> Spago (BuildEnv a) Unit run opts = do logInfo "Building..." - { dependencies, workspace, logOptions } <- ask + { dependencies, workspace, logOptions, psaConfig } <- ask let -- depsOnly means "no packages from the monorepo", so we filter out the workspace packages Tuple dependencyLibs dependencyGlobs = Array.unzip $ (Tuple.uncurry $ Config.sourceGlob' WithTestGlobs) =<< case opts.depsOnly of @@ -82,10 +88,29 @@ run opts = do , color: logOptions.color , jsonErrors: false } + stashFileFallback = case workspace.selected of + Just p -> Just $ Path.concat [ Paths.localCacheStashesPath, "." <> PackageName.print p.package.name ] + Nothing -> Just Paths.localCachesStashEntireWorkspace + psaOptions = + { strict: fromMaybe Psa.defaultParseOptions.strict psaConfig.strict + , censorWarnings: fromMaybe Psa.defaultParseOptions.censorWarnings psaConfig.censorWarnings + , censorLib: fromMaybe Psa.defaultParseOptions.censorLib psaConfig.censorLib + , censorSrc: fromMaybe Psa.defaultParseOptions.censorSrc psaConfig.censorSrc + , showSource: fromMaybe Psa.defaultParseOptions.showSource psaConfig.showSource + , censorCodes: maybe Psa.defaultParseOptions.censorCodes NonEmptySet.toSet psaConfig.censorCodes + , filterCodes: maybe Psa.defaultParseOptions.filterCodes NonEmptySet.toSet psaConfig.filterCodes + , statVerbosity: fromMaybe Psa.defaultParseOptions.statVerbosity psaConfig.statVerbosity + , stashFile: do + Alternative.guard (not opts.depsOnly) + psaConfig.stashFile >>= case _ of + Left true -> stashFileFallback + Left false -> Nothing + Right f -> Just f + } buildBackend globs = do case workspace.backend of Nothing -> - Psa.psaCompile globs (addOutputArgs opts.pursArgs) psaArgs + Psa.psaCompile globs (addOutputArgs opts.pursArgs) psaArgs psaOptions Just backend -> do when (isJust $ Cmd.findFlag { flags: [ "-g", "--codegen" ], args: opts.pursArgs }) do die @@ -94,7 +119,7 @@ run opts = do , "Remove the argument to solve the error" ] let args = (addOutputArgs opts.pursArgs) <> [ "--codegen", "corefn" ] - Psa.psaCompile globs args psaArgs + Psa.psaCompile globs args psaArgs psaOptions logInfo $ "Compiling with backend \"" <> backend.cmd <> "\"" logDebug $ "Running command `" <> backend.cmd <> "`" diff --git a/spaghetto/src/Spago/Command/Init.purs b/spaghetto/src/Spago/Command/Init.purs index 49f22f807..67e53b8fb 100644 --- a/spaghetto/src/Spago/Command/Init.purs +++ b/spaghetto/src/Spago/Command/Init.purs @@ -82,11 +82,13 @@ defaultConfig name set = ] ) , description: Nothing + , build: Nothing , run: Nothing , test: Just { dependencies: Dependencies Map.empty , execArgs: Nothing , main: "Test.Main" + , psaOptions: Nothing } , publish: Nothing , bundle: Nothing diff --git a/spaghetto/src/Spago/Command/Publish.purs b/spaghetto/src/Spago/Command/Publish.purs index b4c76fc04..47195998d 100644 --- a/spaghetto/src/Spago/Command/Publish.purs +++ b/spaghetto/src/Spago/Command/Publish.purs @@ -19,7 +19,7 @@ import Registry.Solver as Registry.Solver import Registry.Version as Version import Spago.BuildInfo as BuildInfo import Spago.Command.Build as Build -import Spago.Config (Package(..), WithTestGlobs(..), Workspace, WorkspacePackage) +import Spago.Config (Package(..), WithTestGlobs(..), Workspace, WorkspacePackage, PsaConfig) import Spago.Config as Config import Spago.Git (Git) import Spago.Git as Git @@ -46,6 +46,7 @@ type PublishEnv a = , purs :: Purs , selected :: WorkspacePackage , dependencies :: Map PackageName Package + , psaConfig :: PsaConfig | a } diff --git a/spaghetto/src/Spago/Config.purs b/spaghetto/src/Spago/Config.purs index 8741f17da..029bcac0f 100644 --- a/spaghetto/src/Spago/Config.purs +++ b/spaghetto/src/Spago/Config.purs @@ -60,6 +60,7 @@ type Workspace = type BuildOptions = { output :: Maybe FilePath , pedanticPackages :: Boolean + , psaOptions :: Maybe Core.PsaConfig } fromExtraPackage :: Core.ExtraPackage -> Package @@ -299,6 +300,7 @@ readWorkspace maybeSelectedPackage = do (buildOptions :: BuildOptions) = { output: _.output =<< workspace.build_opts , pedanticPackages: fromMaybe false (_.pedantic_packages =<< workspace.build_opts) + , psaOptions: _.psaOptions =<< workspace.build_opts } pure diff --git a/spaghetto/src/Spago/Paths.purs b/spaghetto/src/Spago/Paths.purs index d6072a6a1..b6f42df4c 100644 --- a/spaghetto/src/Spago/Paths.purs +++ b/spaghetto/src/Spago/Paths.purs @@ -36,3 +36,9 @@ registryPath = Path.concat [ globalCachePath, "registry" ] registryIndexPath ∷ FilePath registryIndexPath = Path.concat [ globalCachePath, "registry-index" ] + +localCacheStashesPath :: FilePath +localCacheStashesPath = Path.concat [ localCachePath, "stashes" ] + +localCachesStashEntireWorkspace :: FilePath +localCachesStashEntireWorkspace = Path.concat [ localCacheStashesPath, ".entire-workspace" ] diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index cd535658d..ec6166d25 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -38,7 +38,7 @@ type PsaArgs = defaultParseOptions :: PsaOptions defaultParseOptions = - { showSource: true + { showSource: Core.ShowSourceCode , stashFile: Nothing -- ".psa-stash" , censorWarnings: false , censorLib: false @@ -50,7 +50,7 @@ defaultParseOptions = } type PsaOptions = - { showSource :: Boolean + { showSource :: Core.ShowSourceCode , stashFile :: Maybe String , censorWarnings :: Boolean , censorLib :: Boolean @@ -74,11 +74,8 @@ toOutputOptions { libraryDirs, color } options = , strict: options.strict } -psaCompile :: forall a. Set.Set FilePath -> Array String -> PsaArgs -> Spago (Purs.PursEnv a) Unit -psaCompile globs pursArgs psaArgs = psaCompile' globs pursArgs psaArgs defaultParseOptions - -psaCompile' :: forall a. Set.Set FilePath -> Array String -> PsaArgs -> PsaOptions -> Spago (Purs.PursEnv a) Unit -psaCompile' globs pursArgs psaArgs options@{ showSource, stashFile } = do +psaCompile :: forall a. Set.Set FilePath -> Array String -> PsaArgs -> PsaOptions -> Spago (Purs.PursEnv a) Unit +psaCompile globs pursArgs psaArgs options@{ showSource, stashFile } = do let outputOptions = toOutputOptions psaArgs options stashData <- case stashFile of Just f -> readStashFile f @@ -102,7 +99,7 @@ psaCompile' globs pursArgs psaArgs options@{ showSource, stashFile } = do Right out -> do files <- liftEffect $ Ref.new FO.empty let - loadLinesImpl = if showSource then loadLines files else loadNothing + loadLinesImpl = if showSource == Core.ShowSourceCode then loadLines files else loadNothing filenames = insertFilenames (insertFilenames Set.empty out.errors) out.warnings merged <- mergeWarnings filenames stashData.date stashData.stash out.warnings for_ stashFile \f -> writeStashFile f merged From 2febe4defc549e95d3497f2828db9b8a03686ece Mon Sep 17 00:00:00 2001 From: Fabrizio Ferrai Date: Sun, 2 Apr 2023 18:13:08 +0300 Subject: [PATCH 34/78] Compile --- spaghetto/bin/src/Main.purs | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/spaghetto/bin/src/Main.purs b/spaghetto/bin/src/Main.purs index c8df36f8a..97de49c53 100644 --- a/spaghetto/bin/src/Main.purs +++ b/spaghetto/bin/src/Main.purs @@ -47,6 +47,7 @@ import Spago.Json as Json import Spago.Log (LogVerbosity(..)) import Spago.Paths as Paths import Spago.Psa (PsaOptions) +import Spago.Purs (Purs) import Spago.Purs as Purs import Unsafe.Coerce (unsafeCoerce) @@ -165,6 +166,7 @@ type BundleArgs = type PublishArgs = { selectedPackage :: Maybe String + , psaArgs :: PsaArgs } data SpagoCmd a = SpagoCmd GlobalArgs (Command a) @@ -385,6 +387,7 @@ publishArgsParser :: ArgParser PublishArgs publishArgsParser = ArgParser.fromRecord { selectedPackage: Flags.selectedPackage + , psaArgs: psaArgsParser } registrySearchArgsParser :: ArgParser RegistrySearchArgs @@ -468,12 +471,23 @@ main = buildEnv <- runSpago env (mkBuildEnv args dependencies) let options = { depsOnly: false, pursArgs: List.toUnfoldable args.pursArgs } runSpago buildEnv (Build.run options) - Publish { selectedPackage } -> do + Publish { selectedPackage, psaArgs } -> do { env, fetchOpts } <- mkFetchEnv { packages: mempty, selectedPackage, ensureRanges: false } -- TODO: --no-fetch flag dependencies <- runSpago env (Fetch.run fetchOpts) - env' <- runSpago env (mkBuildEnv { depsOnly: false, pursArgs: [] } dependencies) - publishEnv <- runSpago env' (mkPublishEnv dependencies) + let + buildArgs = + { selectedPackage + , psaArgs + , pursArgs: mempty + , backendArgs: mempty + , output: mempty + , pedanticPackages: false + , ensureRanges: false + , jsonErrors: false + } + { purs, psaConfig } <- runSpago env (mkBuildEnv buildArgs dependencies) + publishEnv <- runSpago env (mkPublishEnv dependencies purs psaConfig) void $ runSpago publishEnv (Publish.publish {}) Repl args -> do -- TODO implement @@ -706,10 +720,9 @@ mkBuildEnv buildArgs dependencies = do pure { logOptions, purs, git, dependencies, workspace: newWorkspace, psaConfig } -mkPublishEnv :: forall a. Map PackageName Package -> Spago (Build.BuildEnv a) (Publish.PublishEnv a) -mkPublishEnv dependencies = do +mkPublishEnv :: forall a. Map PackageName Package -> Purs -> Config.PsaConfig -> Spago (Fetch.FetchEnv a) (Publish.PublishEnv a) +mkPublishEnv dependencies purs psaConfig = do env <- ask - purs <- Purs.getPurs selected <- case env.workspace.selected of Just s -> pure s Nothing -> @@ -725,7 +738,7 @@ mkPublishEnv dependencies = do [ toDoc "No package was selected for publishing. Please select (with -p) one of the following packages:" , indent (toDoc $ map _.package.name workspacePackages) ] - pure (Record.union { purs, selected, dependencies } env) + pure (Record.union { purs, selected, dependencies, psaConfig } env) mkFetchEnv :: forall a. FetchArgs -> Spago (LogEnv a) { env :: Fetch.FetchEnv (), fetchOpts :: Fetch.FetchOpts } mkFetchEnv args = do From e2a02f7dab34d10010d1c292829ac716d3b8d590 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 06:39:54 -0500 Subject: [PATCH 35/78] Cleanup import warnings --- spaghetto/bin/src/Main.purs | 3 --- 1 file changed, 3 deletions(-) diff --git a/spaghetto/bin/src/Main.purs b/spaghetto/bin/src/Main.purs index 97de49c53..ef7362ad3 100644 --- a/spaghetto/bin/src/Main.purs +++ b/spaghetto/bin/src/Main.purs @@ -11,9 +11,7 @@ import Data.Codec.Argonaut.Common as CA.Common import Data.JSDate as JSDate import Data.List as List import Data.Map as Map -import Data.Set as Set import Data.Set.NonEmpty (NonEmptySet) -import Data.Set.NonEmpty as NonEmptySet import Effect.Aff as Aff import Effect.Class.Console as Console import Effect.Ref as Ref @@ -46,7 +44,6 @@ import Spago.Git as Git import Spago.Json as Json import Spago.Log (LogVerbosity(..)) import Spago.Paths as Paths -import Spago.Psa (PsaOptions) import Spago.Purs (Purs) import Spago.Purs as Purs import Unsafe.Coerce (unsafeCoerce) From 2de85526bbc1a3d0597b8ae3ca2a727271cac54d Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 06:42:57 -0500 Subject: [PATCH 36/78] Remove flag defaults This causes the config values to never be considered when the flag itself is not provided. --- spaghetto/bin/src/Flags.purs | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/spaghetto/bin/src/Flags.purs b/spaghetto/bin/src/Flags.purs index 8b9eec70e..b2119c49a 100644 --- a/spaghetto/bin/src/Flags.purs +++ b/spaghetto/bin/src/Flags.purs @@ -17,38 +17,33 @@ selectedPackage = "Select the local project to build" # ArgParser.optional -configBoolean' :: Boolean -> ArgParser Unit -> ArgParser (Maybe Boolean) -configBoolean' b p = ArgParser.default (Just b) $ Just (not b) <$ p - -configBooleanTrue :: ArgParser Unit -> ArgParser (Maybe Boolean) -configBooleanTrue = configBoolean' true - -configBooleanFalse :: ArgParser Unit -> ArgParser (Maybe Boolean) -configBooleanFalse = configBoolean' false - psaStrict ∷ ArgParser (Maybe Boolean) psaStrict = ArgParser.flag [ "--strict" ] "Promotes project sources' warnings to errors" - # configBooleanFalse + # ArgParser.boolean + # ArgParser.optional psaCensorWarnings ∷ ArgParser (Maybe Boolean) psaCensorWarnings = ArgParser.flag [ "--psa-censor-warnings" ] "Censor all warnings" - # configBooleanFalse + # ArgParser.boolean + # ArgParser.optional psaCensorLib ∷ ArgParser (Maybe Boolean) psaCensorLib = ArgParser.flag [ "--psa-censor-lib" ] "Censor warnings from library sources" - # configBooleanFalse + # ArgParser.boolean + # ArgParser.optional psaCensorSrc ∷ ArgParser (Maybe Boolean) psaCensorSrc = ArgParser.flag [ "--psa-censor-src" ] "Censor warnings from project sources" - # configBooleanFalse + # ArgParser.boolean + # ArgParser.optional psaShowSource ∷ ArgParser (Maybe ShowSourceCode) psaShowSource = From 32da4fc3b8bc7c52bf4e678da2923a4b328aadad Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 06:52:37 -0500 Subject: [PATCH 37/78] Pass json errors through to build --- spaghetto/bin/src/Main.purs | 20 ++++++++++---------- spaghetto/src/Spago/Command/Build.purs | 3 ++- spaghetto/src/Spago/Command/Publish.purs | 4 ++-- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/spaghetto/bin/src/Main.purs b/spaghetto/bin/src/Main.purs index ef7362ad3..6d42aa8fb 100644 --- a/spaghetto/bin/src/Main.purs +++ b/spaghetto/bin/src/Main.purs @@ -454,19 +454,19 @@ main = RegistryInfo args -> do env <- mkRegistryEnv void $ runSpago env (Registry.info args) - Install args@{ packages, selectedPackage, ensureRanges } -> do + Install args@{ packages, selectedPackage, ensureRanges, jsonErrors } -> do { env, fetchOpts } <- mkFetchEnv { packages, selectedPackage, ensureRanges } -- TODO: --no-fetch flag dependencies <- runSpago env (Fetch.run fetchOpts) env' <- runSpago env (mkBuildEnv args dependencies) - let options = { depsOnly: true, pursArgs: List.toUnfoldable args.pursArgs } + let options = { depsOnly: true, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors } runSpago env' (Build.run options) - Build args@{ selectedPackage, ensureRanges } -> do + Build args@{ selectedPackage, ensureRanges, jsonErrors } -> do { env, fetchOpts } <- mkFetchEnv { packages: mempty, selectedPackage, ensureRanges } -- TODO: --no-fetch flag dependencies <- runSpago env (Fetch.run fetchOpts) buildEnv <- runSpago env (mkBuildEnv args dependencies) - let options = { depsOnly: false, pursArgs: List.toUnfoldable args.pursArgs } + let options = { depsOnly: false, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors } runSpago buildEnv (Build.run options) Publish { selectedPackage, psaArgs } -> do { env, fetchOpts } <- mkFetchEnv { packages: mempty, selectedPackage, ensureRanges: false } @@ -489,33 +489,33 @@ main = Repl args -> do -- TODO implement pure unit - Bundle args@{ selectedPackage, ensureRanges } -> do + Bundle args@{ selectedPackage, ensureRanges, jsonErrors } -> do { env, fetchOpts } <- mkFetchEnv { packages: mempty, selectedPackage, ensureRanges } -- TODO: --no-fetch flag dependencies <- runSpago env (Fetch.run fetchOpts) -- TODO: --no-build flag buildEnv <- runSpago env (mkBuildEnv args dependencies) - let options = { depsOnly: false, pursArgs: List.toUnfoldable args.pursArgs } + let options = { depsOnly: false, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors } runSpago buildEnv (Build.run options) bundleEnv <- runSpago env (mkBundleEnv args) runSpago bundleEnv Bundle.run - Run args@{ selectedPackage, ensureRanges } -> do + Run args@{ selectedPackage, ensureRanges, jsonErrors } -> do { env, fetchOpts } <- mkFetchEnv { packages: mempty, selectedPackage, ensureRanges } -- TODO: --no-fetch flag dependencies <- runSpago env (Fetch.run fetchOpts) -- TODO: --no-build flag buildEnv <- runSpago env (mkBuildEnv args dependencies) - let options = { depsOnly: false, pursArgs: List.toUnfoldable args.pursArgs } + let options = { depsOnly: false, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors } runSpago buildEnv (Build.run options) runEnv <- runSpago env (mkRunEnv args) runSpago runEnv Run.run - Test args@{ selectedPackage } -> do + Test args@{ selectedPackage, jsonErrors } -> do { env, fetchOpts } <- mkFetchEnv { packages: mempty, selectedPackage, ensureRanges: false } -- TODO: --no-fetch flag dependencies <- runSpago env (Fetch.run fetchOpts) -- TODO: --no-build flag buildEnv <- runSpago env (mkBuildEnv (Record.union args { ensureRanges: false }) dependencies) - let options = { depsOnly: false, pursArgs: List.toUnfoldable args.pursArgs } + let options = { depsOnly: false, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors } runSpago buildEnv (Build.run options) testEnv <- runSpago env (mkTestEnv args) runSpago testEnv Test.run diff --git a/spaghetto/src/Spago/Command/Build.purs b/spaghetto/src/Spago/Command/Build.purs index 287e4722c..752994898 100644 --- a/spaghetto/src/Spago/Command/Build.purs +++ b/spaghetto/src/Spago/Command/Build.purs @@ -36,6 +36,7 @@ type BuildEnv a = type BuildOptions = { depsOnly :: Boolean , pursArgs :: Array String + , jsonErrors :: Boolean } run :: forall a. BuildOptions -> Spago (BuildEnv a) Unit @@ -86,7 +87,7 @@ run opts = do psaArgs = { libraryDirs: dependencyLibs , color: logOptions.color - , jsonErrors: false + , jsonErrors: opts.jsonErrors } stashFileFallback = case workspace.selected of Just p -> Just $ Path.concat [ Paths.localCacheStashesPath, "." <> PackageName.print p.package.name ] diff --git a/spaghetto/src/Spago/Command/Publish.purs b/spaghetto/src/Spago/Command/Publish.purs index 47195998d..239c4b082 100644 --- a/spaghetto/src/Spago/Command/Publish.purs +++ b/spaghetto/src/Spago/Command/Publish.purs @@ -91,7 +91,7 @@ publish _args = do -- As first thing we run a build to make sure the package compiles at all runSpago (env { workspace = workspace { selected = Just selected } }) - (Build.run { depsOnly: false, pursArgs: [] }) + (Build.run { depsOnly: false, pursArgs: [], jsonErrors: false }) -- We then need to check that the dependency graph is accurate. If not, queue the errors let globs = getGlobs selected dependencies @@ -237,7 +237,7 @@ publish _args = do , dependencies = buildPlanDependencies } ) - (Build.run { depsOnly: false, pursArgs: [] }) + (Build.run { depsOnly: false, pursArgs: [], jsonErrors: false }) logDebug $ unsafeStringify publishingData logSuccess "Ready for publishing. Calling the registry.." From fce2abf984c42dbac63bf939ed088d43dceda30e Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 07:07:03 -0500 Subject: [PATCH 38/78] Update package set (get new node execa version) --- spaghetto/spago.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spaghetto/spago.yaml b/spaghetto/spago.yaml index 8280142d7..62ea7fe54 100644 --- a/spaghetto/spago.yaml +++ b/spaghetto/spago.yaml @@ -48,9 +48,9 @@ package: - versions workspace: package_set: - # url: https://raw.githubusercontent.com/purescript/package-sets/psc-0.15.7-20230207/packages.json - # url: https://raw.githubusercontent.com/purescript/registry/main/package-sets/11.10.0.json - registry: 11.10.0 + # url: https://raw.githubusercontent.com/purescript/package-sets/psc-0.15.7-20230402/packages.json + # url: https://raw.githubusercontent.com/purescript/registry/main/package-sets/20.0.1.json + registry: 20.0.1 extra_packages: registry-lib: git: https://github.com/purescript/registry-dev.git From a49597ba87a58be01cd27c5d684257b392989623 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 07:09:49 -0500 Subject: [PATCH 39/78] Don't print json errors in terminal --- spaghetto/src/Spago/Purs.purs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spaghetto/src/Spago/Purs.purs b/spaghetto/src/Spago/Purs.purs index e05de0f96..1ba5d411b 100644 --- a/spaghetto/src/Spago/Purs.purs +++ b/spaghetto/src/Spago/Purs.purs @@ -48,7 +48,8 @@ compile globs pursArgs = do { purs } <- ask let args = [ "compile" ] <> pursArgs <> Set.toUnfoldable globs logDebug [ "Running command:", "purs " <> String.joinWith " " args ] - Cmd.exec purs.cmd args Cmd.defaultExecOptions + Cmd.exec purs.cmd args $ Cmd.defaultExecOptions + { pipeStdout = false } -------------------------------------------------------------------------------- -- Graph From 654bfdbd852976767a576f8a5a7616a56fc8346f Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 07:09:57 -0500 Subject: [PATCH 40/78] Drop redundant import --- spaghetto/src/Spago/Purs.purs | 1 - 1 file changed, 1 deletion(-) diff --git a/spaghetto/src/Spago/Purs.purs b/spaghetto/src/Spago/Purs.purs index 1ba5d411b..e7fc7f25f 100644 --- a/spaghetto/src/Spago/Purs.purs +++ b/spaghetto/src/Spago/Purs.purs @@ -8,7 +8,6 @@ import Data.Codec.Argonaut.Record as CAR import Data.Profunctor as Profunctor import Data.Set as Set import Data.String as String -import Node.Library.Execa as Execa import Registry.Internal.Codec as Internal.Codec import Registry.Version as Version import Spago.Cmd as Cmd From d2ecdc57b095d55d1c634c04cc266312654db590 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 07:13:32 -0500 Subject: [PATCH 41/78] Fix codecs: use nullable Maybe codec --- spaghetto/src/Spago/Psa/Types.purs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/spaghetto/src/Spago/Psa/Types.purs b/spaghetto/src/Spago/Psa/Types.purs index d9eea0748..5ca42f5a4 100644 --- a/spaghetto/src/Spago/Psa/Types.purs +++ b/spaghetto/src/Spago/Psa/Types.purs @@ -25,7 +25,6 @@ import Prelude import Data.Codec.Argonaut.Record as CAR import Data.Codec.Argonaut as CA -import Data.Codec.Argonaut.Common as CAC import Data.Codec.Argonaut.Compat as CACompat import Data.Maybe (Maybe(..)) import Data.Set (Set) @@ -118,11 +117,11 @@ psaResultCodec = CAR.object "PsaResult" psaErrorCodec :: CA.JsonCodec PsaError psaErrorCodec = CAR.object "PsaError" - { moduleName: CAC.maybe CA.string + { moduleName: CACompat.maybe CA.string , errorCode: CA.string , errorLink: CA.string , message: CA.string - , filename: CAC.maybe CA.string + , filename: CACompat.maybe CA.string , position: CACompat.maybe positionCodec , suggestion: CACompat.maybe suggestionCodec } From c832104c4215660347d86cabc0867f37319cae4f Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 07:18:22 -0500 Subject: [PATCH 42/78] Add missing newline between error header & code --- spaghetto/src/Spago/Psa/Printer/Default.purs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spaghetto/src/Spago/Psa/Printer/Default.purs b/spaghetto/src/Spago/Psa/Printer/Default.purs index cede1d4e6..ef7f179d3 100644 --- a/spaghetto/src/Spago/Psa/Printer/Default.purs +++ b/spaghetto/src/Spago/Psa/Printer/Default.purs @@ -65,12 +65,11 @@ renderError = renderWrapper Ansi.Red renderWrapper :: Ansi.Color -> Int -> Int -> PsaAnnotedError -> D.Doc Ansi.GraphicsParam renderWrapper color total index { error, path, position, source, message } = - D.lines + D.foldWithSeparator (D.break <> D.break) [ D.words $ [ renderStatus color total index error.errorCode , renderPath path error.moduleName <> foldMap renderPosition position ] - , D.text "" , D.indent $ D.lines [ fromMaybe mempty (renderSource' <$> position <*> source) , toLines message From a6622ef875170200997207842c28f0a4f9337bb9 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 07:18:34 -0500 Subject: [PATCH 43/78] Format imports --- spaghetto/src/Spago/Psa/Printer/Default.purs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spaghetto/src/Spago/Psa/Printer/Default.purs b/spaghetto/src/Spago/Psa/Printer/Default.purs index ef7f179d3..d10d9304a 100644 --- a/spaghetto/src/Spago/Psa/Printer/Default.purs +++ b/spaghetto/src/Spago/Psa/Printer/Default.purs @@ -14,16 +14,16 @@ module Spago.Psa.Printer.Default import Prelude -import Control.Alternative as Alternative import Ansi.Codes as Ansi +import Control.Alternative as Alternative import Data.Array as Array import Data.Foldable (fold, foldMap, maximum, maximumBy) +import Data.FoldableWithIndex (forWithIndex_) import Data.Maybe (Maybe(..), fromMaybe, maybe) import Data.Monoid (power) -import Data.FoldableWithIndex (forWithIndex_) -import Data.Unfoldable (unfoldr) import Data.String as Str import Data.Tuple (Tuple(..), uncurry) +import Data.Unfoldable (unfoldr) import Dodo as D import Dodo.Ansi as DA import Effect (Effect) From e1345c32299f6307a67c6dbba4dbf560fdbb4f38 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 07:27:03 -0500 Subject: [PATCH 44/78] Print json errors to stdout, not stderr --- spaghetto/src/Spago/Psa/Printer/Json.purs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spaghetto/src/Spago/Psa/Printer/Json.purs b/spaghetto/src/Spago/Psa/Printer/Json.purs index ba2c054a3..5869fe32f 100644 --- a/spaghetto/src/Spago/Psa/Printer/Json.purs +++ b/spaghetto/src/Spago/Psa/Printer/Json.purs @@ -19,4 +19,4 @@ print output = do , errors: _.error <$> output.errors } - Console.error (stringify result) + Console.log (stringify result) From b5102bc6e7a86796a9777f03b53fae29608ac86d Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 07:40:56 -0500 Subject: [PATCH 45/78] Make file's dir before writing to file --- spaghetto/src/Spago/Psa.purs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index ec6166d25..eb384957c 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -22,7 +22,10 @@ import Effect.Ref as Ref import Foreign.Object as FO import Node.Encoding as Encoding import Node.FS.Aff as FSA +import Node.FS.Perms (permsAll) import Node.FS.Stats as Stats +import Node.FS.Sync as FSSync +import Node.Path (dirname) import Spago.Core.Config as Core import Spago.Psa.Output (buildOutput) import Spago.Psa.Printer.Default as DefaultPrinter @@ -175,7 +178,12 @@ psaCompile globs pursArgs psaArgs options@{ showSource, stashFile } = do writeStashFile stashFile' warnings = do logDebug $ "Writing stash file: " <> stashFile' - let file = stringify (encodeStash warnings) + let + file = stringify (encodeStash warnings) + dir = dirname stashFile' + dirExists <- liftEffect $ FSSync.exists dir + unless dirExists do + liftAff $ FSA.mkdir' dir { recursive: true, mode: permsAll } liftAff $ FSA.writeTextFile Encoding.UTF8 stashFile' file mergeWarnings filenames date old new = do From d43f8f47466af1208e31a7c336449d06df6eadd6 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 07:50:30 -0500 Subject: [PATCH 46/78] Use different arg name for stash file Using `stash` as a CLI arg and flag, independent of order, will only cause the first to work --- spaghetto/bin/src/Flags.purs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spaghetto/bin/src/Flags.purs b/spaghetto/bin/src/Flags.purs index b2119c49a..a41cdb5d9 100644 --- a/spaghetto/bin/src/Flags.purs +++ b/spaghetto/bin/src/Flags.purs @@ -76,7 +76,7 @@ psaStatVerbosity = ArgParser.optional $ ArgParser.choose "StatVerbosity" psaStashFile ∷ ArgParser (Maybe (Either Boolean String)) psaStashFile = ArgParser.optional $ ArgParser.choose "stash" - [ ArgParser.argument [ "--psa-stash" ] "Enable persistent warnings using a specific stash file" + [ ArgParser.argument [ "--psa-stash-file" ] "Enable persistent warnings using a specific stash file" # ArgParser.unformat "FILE" (Right <<< Right) , Left true <$ ArgParser.flag [ "--psa-stash" ] "Enable persistent warnings using default stash file location" ] From 43a755385dc4a8fd325c795f81e4bf2757549f33 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 07:50:57 -0500 Subject: [PATCH 47/78] Update docs --- spaghetto/bin/src/Flags.purs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spaghetto/bin/src/Flags.purs b/spaghetto/bin/src/Flags.purs index a41cdb5d9..5971357f6 100644 --- a/spaghetto/bin/src/Flags.purs +++ b/spaghetto/bin/src/Flags.purs @@ -76,7 +76,7 @@ psaStatVerbosity = ArgParser.optional $ ArgParser.choose "StatVerbosity" psaStashFile ∷ ArgParser (Maybe (Either Boolean String)) psaStashFile = ArgParser.optional $ ArgParser.choose "stash" - [ ArgParser.argument [ "--psa-stash-file" ] "Enable persistent warnings using a specific stash file" + [ ArgParser.argument [ "--psa-stash-file" ] "Enable persistent warnings using a specific stash file relative to the current working directory" # ArgParser.unformat "FILE" (Right <<< Right) , Left true <$ ArgParser.flag [ "--psa-stash" ] "Enable persistent warnings using default stash file location" ] From 8706edebb58162e17295b6f8cc9beaa2d9c51066 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 07:52:20 -0500 Subject: [PATCH 48/78] End stash file names with '.stash' --- spaghetto/src/Spago/Command/Build.purs | 3 +-- spaghetto/src/Spago/Paths.purs | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/spaghetto/src/Spago/Command/Build.purs b/spaghetto/src/Spago/Command/Build.purs index 752994898..e784f4911 100644 --- a/spaghetto/src/Spago/Command/Build.purs +++ b/spaghetto/src/Spago/Command/Build.purs @@ -11,7 +11,6 @@ import Data.Map as Map import Data.Set as Set import Data.Set.NonEmpty as NonEmptySet import Data.Tuple as Tuple -import Node.Path as Path import Registry.PackageName as PackageName import Spago.BuildInfo as BuildInfo import Spago.Cmd as Cmd @@ -90,7 +89,7 @@ run opts = do , jsonErrors: opts.jsonErrors } stashFileFallback = case workspace.selected of - Just p -> Just $ Path.concat [ Paths.localCacheStashesPath, "." <> PackageName.print p.package.name ] + Just p -> Just $ Paths.mkLocalCachesStashFile $ PackageName.print p.package.name Nothing -> Just Paths.localCachesStashEntireWorkspace psaOptions = { strict: fromMaybe Psa.defaultParseOptions.strict psaConfig.strict diff --git a/spaghetto/src/Spago/Paths.purs b/spaghetto/src/Spago/Paths.purs index b6f42df4c..3d072ddc0 100644 --- a/spaghetto/src/Spago/Paths.purs +++ b/spaghetto/src/Spago/Paths.purs @@ -41,4 +41,7 @@ localCacheStashesPath :: FilePath localCacheStashesPath = Path.concat [ localCachePath, "stashes" ] localCachesStashEntireWorkspace :: FilePath -localCachesStashEntireWorkspace = Path.concat [ localCacheStashesPath, ".entire-workspace" ] +localCachesStashEntireWorkspace = mkLocalCachesStashFile "entire-workspace" + +mkLocalCachesStashFile :: String -> FilePath +mkLocalCachesStashFile fileName = Path.concat [ localCacheStashesPath, fileName <> ".stash" ] From 042608b9f91e6dc60e79fed9a683d45c95076629 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 07:56:13 -0500 Subject: [PATCH 49/78] Make ansi colors bright --- spaghetto/src/Spago/Psa/Printer/Default.purs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/spaghetto/src/Spago/Psa/Printer/Default.purs b/spaghetto/src/Spago/Psa/Printer/Default.purs index d10d9304a..e6a0a7cd0 100644 --- a/spaghetto/src/Spago/Psa/Printer/Default.purs +++ b/spaghetto/src/Spago/Psa/Printer/Default.purs @@ -58,10 +58,10 @@ print options output = do Core.VerboseStats -> renderVerboseStats renderWarning :: Int -> Int -> PsaAnnotedError -> D.Doc Ansi.GraphicsParam -renderWarning = renderWrapper Ansi.Yellow +renderWarning = renderWrapper Ansi.BrightYellow renderError :: Int -> Int -> PsaAnnotedError -> D.Doc Ansi.GraphicsParam -renderError = renderWrapper Ansi.Red +renderError = renderWrapper Ansi.BrightRed renderWrapper :: Ansi.Color -> Int -> Int -> PsaAnnotedError -> D.Doc Ansi.GraphicsParam renderWrapper color total index { error, path, position, source, message } = @@ -106,7 +106,7 @@ renderSource' pos lines = renderSource pos lines <> D.break renderStats :: OutputStats -> D.Doc Ansi.GraphicsParam renderStats stats = renderStatCols - { col1: [ renderLabel Ansi.Yellow "Warnings", renderLabel Ansi.Red "Errors" ] + { col1: [ renderLabel Ansi.BrightYellow "Warnings", renderLabel Ansi.BrightRed "Errors" ] , col2: [ renderStat srcWarnings, renderStat srcErrors ] , col3: [ renderStat libWarnings, renderStat libErrors ] , col4: [ renderStat allWarnings, renderStat allErrors ] @@ -139,8 +139,8 @@ renderVerboseStats stats = , doc: DA.foreground color $ D.text lbl } - warningLabels = renderLabel Ansi.Yellow <$> warnings - errorLabels = renderLabel Ansi.Red <$> errors + warningLabels = renderLabel Ansi.BrightYellow <$> warnings + errorLabels = renderLabel Ansi.BrightRed <$> errors getStat key x = fromMaybe (Tuple 0 0) $ FO.lookup key x getStats ks x = (\k -> renderStat $ getStat k x) <$> ks @@ -217,7 +217,7 @@ renderStatCols' { col1, col2, col3, col4 } = D.lines rows pure $ flip Tuple (rowIdx + 1) $ guttered [ c1, c2, c3, c4 ] renderStat :: Tuple Int Int -> DocColumn -renderStat (Tuple 0 0) = { width: 1, alignLeft: false, doc: DA.foreground Ansi.Green $ D.text "0" } +renderStat (Tuple 0 0) = { width: 1, alignLeft: false, doc: DA.foreground Ansi.BrightGreen $ D.text "0" } renderStat (Tuple a b) | a == b = do let aText = show a @@ -262,13 +262,13 @@ sourceLine gutter sep num code = fold renderErrorRange :: Int -> Int -> D.Doc Ansi.GraphicsParam renderErrorRange start len = fold [ D.text $ power " " (start - 1) - , DA.foreground Ansi.Red $ D.text $ power "^" len + , DA.foreground Ansi.BrightRed $ D.text $ power "^" len ] renderErrorTick :: Int -> String -> D.Doc Ansi.GraphicsParam renderErrorTick start char = fold [ D.text $ power " " (start - 1) - , DA.foreground Ansi.Red $ D.text char + , DA.foreground Ansi.BrightRed $ D.text char ] padLeft :: Int -> String -> String From 7a6ea2784c612fd50a43a6aa5d4dc90f25f8b42e Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 08:06:23 -0500 Subject: [PATCH 50/78] Separate default from custom stashes; security - Separating the two ensures a person using a custom stash file 'foo' for the package 'foo' does not overwrite/reuse the default stash file for 'foo' if it already exists - When a custom stash file location is used, we use only the base name to prevent the user from accidentally overwriting some other file beyond this one (e.g. --psa-stash-file="../../../.ssh/id_rsa") --- spaghetto/bin/src/Flags.purs | 4 +++- spaghetto/src/Spago/Command/Build.purs | 2 +- spaghetto/src/Spago/Paths.purs | 15 ++++++++++++--- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/spaghetto/bin/src/Flags.purs b/spaghetto/bin/src/Flags.purs index 5971357f6..9ce987f49 100644 --- a/spaghetto/bin/src/Flags.purs +++ b/spaghetto/bin/src/Flags.purs @@ -8,8 +8,10 @@ import Data.Array.NonEmpty as NEA import Data.Set.NonEmpty (NonEmptySet) import Data.Set.NonEmpty as NonEmptySet import Data.String as String +import Node.Path as Path import Spago.Core.Config (ShowSourceCode(..)) import Spago.Core.Config as Core +import Spago.Paths as Paths selectedPackage ∷ ArgParser (Maybe String) selectedPackage = @@ -77,7 +79,7 @@ psaStatVerbosity = ArgParser.optional $ ArgParser.choose "StatVerbosity" psaStashFile ∷ ArgParser (Maybe (Either Boolean String)) psaStashFile = ArgParser.optional $ ArgParser.choose "stash" [ ArgParser.argument [ "--psa-stash-file" ] "Enable persistent warnings using a specific stash file relative to the current working directory" - # ArgParser.unformat "FILE" (Right <<< Right) + # ArgParser.unformat "FILE" (Right <<< Right <<< Paths.mkLocalCachesCustomStashFile <<< Path.basename) , Left true <$ ArgParser.flag [ "--psa-stash" ] "Enable persistent warnings using default stash file location" ] diff --git a/spaghetto/src/Spago/Command/Build.purs b/spaghetto/src/Spago/Command/Build.purs index e784f4911..b00b5def9 100644 --- a/spaghetto/src/Spago/Command/Build.purs +++ b/spaghetto/src/Spago/Command/Build.purs @@ -89,7 +89,7 @@ run opts = do , jsonErrors: opts.jsonErrors } stashFileFallback = case workspace.selected of - Just p -> Just $ Paths.mkLocalCachesStashFile $ PackageName.print p.package.name + Just p -> Just $ Paths.mkLocalCachesDefaultStashFile $ PackageName.print p.package.name Nothing -> Just Paths.localCachesStashEntireWorkspace psaOptions = { strict: fromMaybe Psa.defaultParseOptions.strict psaConfig.strict diff --git a/spaghetto/src/Spago/Paths.purs b/spaghetto/src/Spago/Paths.purs index 3d072ddc0..688cf743c 100644 --- a/spaghetto/src/Spago/Paths.purs +++ b/spaghetto/src/Spago/Paths.purs @@ -40,8 +40,17 @@ registryIndexPath = Path.concat [ globalCachePath, "registry-index" ] localCacheStashesPath :: FilePath localCacheStashesPath = Path.concat [ localCachePath, "stashes" ] +localCacheStashesDefaultsPath :: FilePath +localCacheStashesDefaultsPath = Path.concat [ localCacheStashesPath, "defaults" ] + +localCacheStashesCustomPath :: FilePath +localCacheStashesCustomPath = Path.concat [ localCacheStashesPath, "custom" ] + localCachesStashEntireWorkspace :: FilePath -localCachesStashEntireWorkspace = mkLocalCachesStashFile "entire-workspace" +localCachesStashEntireWorkspace = mkLocalCachesDefaultStashFile "entire-workspace" + +mkLocalCachesDefaultStashFile :: String -> FilePath +mkLocalCachesDefaultStashFile fileName = Path.concat [ localCacheStashesDefaultsPath, fileName <> ".stash" ] -mkLocalCachesStashFile :: String -> FilePath -mkLocalCachesStashFile fileName = Path.concat [ localCacheStashesPath, fileName <> ".stash" ] +mkLocalCachesCustomStashFile :: String -> FilePath +mkLocalCachesCustomStashFile fileName = Path.concat [ localCacheStashesCustomPath, fileName <> ".stash" ] From 51f2d3b96d501316a1cea67558902f328f4896a3 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 08:09:53 -0500 Subject: [PATCH 51/78] Note which purs args are disallowed --- spaghetto/bin/src/Flags.purs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spaghetto/bin/src/Flags.purs b/spaghetto/bin/src/Flags.purs index 9ce987f49..16163b87b 100644 --- a/spaghetto/bin/src/Flags.purs +++ b/spaghetto/bin/src/Flags.purs @@ -170,7 +170,7 @@ pedanticPackages = pursArgs ∷ ArgParser (List String) pursArgs = ArgParser.argument [ "--purs-args" ] - "Arguments to pass to purs compile. Wrap in quotes." + "Arguments to pass to purs compile. Wrap in quotes. `--output` and `--json-errors` must be passed to Spago directly." # ArgParser.many execArgs :: ArgParser (Maybe (Array String)) From 6ff0543b5cc97ea8d63ff6567958ea7eda2e7f11 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 08:17:41 -0500 Subject: [PATCH 52/78] Simplfiy censor/filter code flags --- spaghetto/bin/src/Flags.purs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/spaghetto/bin/src/Flags.purs b/spaghetto/bin/src/Flags.purs index 16163b87b..a4bb16ac9 100644 --- a/spaghetto/bin/src/Flags.purs +++ b/spaghetto/bin/src/Flags.purs @@ -4,10 +4,8 @@ import Spago.Prelude import ArgParse.Basic (ArgParser) import ArgParse.Basic as ArgParser -import Data.Array.NonEmpty as NEA import Data.Set.NonEmpty (NonEmptySet) import Data.Set.NonEmpty as NonEmptySet -import Data.String as String import Node.Path as Path import Spago.Core.Config (ShowSourceCode(..)) import Spago.Core.Config as Core @@ -56,19 +54,17 @@ psaShowSource = psaCensorCodes :: ArgParser (Maybe (NonEmptySet String)) psaCensorCodes = - ArgParser.argument [ "--psa-censor-codes" ] - "Censor specific error codes (comma-separated list)" - # ArgParser.unformat "CODE1,CODE2,...,CODEX" - (maybe (Left "Did not get a set of values") (Right <<< NonEmptySet.fromFoldable1) <<< NEA.fromArray <<< String.split (String.Pattern ",")) - # ArgParser.optional + ArgParser.argument [ "--psa-censor-code" ] + "Censor a specific error code (e.g. `ShadowedName`)" + # ArgParser.many + <#> NonEmptySet.fromFoldable psaFilterCodes :: ArgParser (Maybe (NonEmptySet String)) psaFilterCodes = - ArgParser.argument [ "--psa-filter-codes" ] - "Only show specific error codes (comma-separated list)" - # ArgParser.unformat "CODE1,CODE2,...,CODEX" - (maybe (Left "Did not get a set of values") (Right <<< NonEmptySet.fromFoldable1) <<< NEA.fromArray <<< String.split (String.Pattern ",")) - # ArgParser.optional + ArgParser.argument [ "--psa-filter-code" ] + "Only show a specific error code (e.g. `TypesDoNotUnify`)" + # ArgParser.many + <#> NonEmptySet.fromFoldable psaStatVerbosity :: ArgParser (Maybe Core.StatVerbosity) psaStatVerbosity = ArgParser.optional $ ArgParser.choose "StatVerbosity" From 3d5066c0771f1923996e6e916efb57bca72edb59 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 08:40:06 -0500 Subject: [PATCH 53/78] Correct flag doc --- spaghetto/bin/src/Flags.purs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spaghetto/bin/src/Flags.purs b/spaghetto/bin/src/Flags.purs index a4bb16ac9..1a6ffb3a8 100644 --- a/spaghetto/bin/src/Flags.purs +++ b/spaghetto/bin/src/Flags.purs @@ -74,7 +74,7 @@ psaStatVerbosity = ArgParser.optional $ ArgParser.choose "StatVerbosity" psaStashFile ∷ ArgParser (Maybe (Either Boolean String)) psaStashFile = ArgParser.optional $ ArgParser.choose "stash" - [ ArgParser.argument [ "--psa-stash-file" ] "Enable persistent warnings using a specific stash file relative to the current working directory" + [ ArgParser.argument [ "--psa-stash-file" ] "Enable persistent warnings using a specific stash file" # ArgParser.unformat "FILE" (Right <<< Right <<< Paths.mkLocalCachesCustomStashFile <<< Path.basename) , Left true <$ ArgParser.flag [ "--psa-stash" ] "Enable persistent warnings using default stash file location" ] From 1b0938809c03a308b3ac6af3edf9d98ec9833c34 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 08:49:55 -0500 Subject: [PATCH 54/78] Update readme's config file docs --- spaghetto/README.md | 47 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/spaghetto/README.md b/spaghetto/README.md index cfbcf2662..f7f066574 100644 --- a/spaghetto/README.md +++ b/spaghetto/README.md @@ -46,6 +46,48 @@ package: # 2. the package, using a specified vesrion range - packageName: ">=1.1.1 <2.0.0" +# optional + build: + # optional + psaOptions: + # optional, Boolean, censor all warnings + censorWarnings: false + # optional, Boolean, censor warnings from library sources + censorLib: false + # optional, Boolean, censor warnings from project sources + censorSrc: false + # optional, NonEmptyArray, censor specific codes + censorCodes: + - ShadowedName + # optional, NonEmptyArray, only show specific codes + filterCodes: + - ShadowedName + # optional, whether to show statistics at the end + # of warning/error output and how much informaiton + statVerbosity: + # One of 3 values + # 1. Don't show it + "no-stats" + # 2. Show it and only sum the total warnings/errors + "compact-stats" + # 3. Show it and show total warnings/errors by code + "verbose-stats" + # optional, boolean, whether to show the source code + # corresponding to the error's location + showSource: true + # optional, boolean, counts compiler warnings as compiler errors + strict: false + # optional, Either Boolean String, enable/disable + # the pretty-printed compiler warnings/errors + # and whether to store them in a non-default location + stashFile: + # one of 3 values + # 1. Disable it + false + # 2. Enable it using default location (.spago/default/) + true + # 3. Enable it using custom location (.spago/custom) + # optional bundle: # optional, Boolean, whether to minify @@ -148,4 +190,9 @@ workspace: output: "output" # optional, Boolean, fail the build if `spago.yml` has redundant/missing packages pedantic_packages: false + # optional, PsaOptions + # These options only take affect when + # a package is not selected (e.g. `spago build` vs `spago build -p pkgName`) + psaOptions: + # see the Package's `psaOptions` field ``` From e0d045eb46bb70f715d3c97011d54f1fca28e6b8 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 09:10:03 -0500 Subject: [PATCH 55/78] Drop unneeded versions dep --- spaghetto/spago.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/spaghetto/spago.yaml b/spaghetto/spago.yaml index 62ea7fe54..99f3ae9be 100644 --- a/spaghetto/spago.yaml +++ b/spaghetto/spago.yaml @@ -45,7 +45,6 @@ package: - transformers - tuples - unsafe-coerce - - versions workspace: package_set: # url: https://raw.githubusercontent.com/purescript/package-sets/psc-0.15.7-20230402/packages.json From 07531a9cbf2d5b53ed12f4dcf4c1b8731dd777bf Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 09:10:54 -0500 Subject: [PATCH 56/78] Fix error message about json-errors config value --- spaghetto/src/Spago/Command/Build.purs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spaghetto/src/Spago/Command/Build.purs b/spaghetto/src/Spago/Command/Build.purs index b00b5def9..8d4cb9953 100644 --- a/spaghetto/src/Spago/Command/Build.purs +++ b/spaghetto/src/Spago/Command/Build.purs @@ -79,7 +79,7 @@ run opts = do when (isJust $ Cmd.findFlag { flags: [ "--json-errors" ], args: opts.pursArgs }) do die [ "Can't pass `--json-errors` option directly to purs." - , "Use the --json-errors flag for Spago, or add it to your config file." + , "Use the --json-errors flag for Spago." ] let From bc6fcc570588b7f6d84f6a5e81f162ed68dca10a Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 09:11:22 -0500 Subject: [PATCH 57/78] Drop ".psa-stash" comment --- spaghetto/src/Spago/Psa.purs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index eb384957c..e19f2f715 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -42,7 +42,7 @@ type PsaArgs = defaultParseOptions :: PsaOptions defaultParseOptions = { showSource: Core.ShowSourceCode - , stashFile: Nothing -- ".psa-stash" + , stashFile: Nothing , censorWarnings: false , censorLib: false , censorSrc: false From d2818f8817698da9005ab014de02a5941510dd4f Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 3 Apr 2023 09:12:15 -0500 Subject: [PATCH 58/78] Fix formatting --- spaghetto/src/Spago/Psa.purs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index e19f2f715..55afd8fc1 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -124,15 +124,7 @@ psaCompile globs pursArgs psaArgs options@{ showSource, stashFile } = do loadNothing _ _ = pure Nothing isEmptySpan filename pos = - filename == "" - || pos.startLine - == 0 - && pos.endLine - == 0 - && pos.startColumn - == 0 - && pos.endColumn - == 0 + filename == "" || pos.startLine == 0 && pos.endLine == 0 && pos.startColumn == 0 && pos.endColumn == 0 -- TODO: Handle exceptions loadLines files filename pos From 9a9aa4329313af81ce4ea017c27f06e45eac3fdd Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 6 Apr 2023 08:33:22 -0500 Subject: [PATCH 59/78] Rename CLI flags --- spaghetto/bin/src/Flags.purs | 56 ++++++++++++++++++------------------ spaghetto/bin/src/Main.purs | 18 ++++++------ 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/spaghetto/bin/src/Flags.purs b/spaghetto/bin/src/Flags.purs index 1a6ffb3a8..f9ff10841 100644 --- a/spaghetto/bin/src/Flags.purs +++ b/spaghetto/bin/src/Flags.purs @@ -17,66 +17,66 @@ selectedPackage = "Select the local project to build" # ArgParser.optional -psaStrict ∷ ArgParser (Maybe Boolean) -psaStrict = +strict ∷ ArgParser (Maybe Boolean) +strict = ArgParser.flag [ "--strict" ] "Promotes project sources' warnings to errors" # ArgParser.boolean # ArgParser.optional -psaCensorWarnings ∷ ArgParser (Maybe Boolean) -psaCensorWarnings = - ArgParser.flag [ "--psa-censor-warnings" ] +censorWarnings ∷ ArgParser (Maybe Boolean) +censorWarnings = + ArgParser.flag [ "---censor-warnings" ] "Censor all warnings" # ArgParser.boolean # ArgParser.optional -psaCensorLib ∷ ArgParser (Maybe Boolean) -psaCensorLib = - ArgParser.flag [ "--psa-censor-lib" ] +censorLib ∷ ArgParser (Maybe Boolean) +censorLib = + ArgParser.flag [ "---censor-lib" ] "Censor warnings from library sources" # ArgParser.boolean # ArgParser.optional -psaCensorSrc ∷ ArgParser (Maybe Boolean) -psaCensorSrc = - ArgParser.flag [ "--psa-censor-src" ] +censorSrc ∷ ArgParser (Maybe Boolean) +censorSrc = + ArgParser.flag [ "---censor-src" ] "Censor warnings from project sources" # ArgParser.boolean # ArgParser.optional -psaShowSource ∷ ArgParser (Maybe ShowSourceCode) -psaShowSource = +showSource ∷ ArgParser (Maybe ShowSourceCode) +showSource = NoSourceCode - <$ ArgParser.flag [ "--psa-no-source" ] + <$ ArgParser.flag [ "---no-source" ] "Disable original source code printing" # ArgParser.optional -psaCensorCodes :: ArgParser (Maybe (NonEmptySet String)) -psaCensorCodes = - ArgParser.argument [ "--psa-censor-code" ] +censorCodes :: ArgParser (Maybe (NonEmptySet String)) +censorCodes = + ArgParser.argument [ "---censor-code" ] "Censor a specific error code (e.g. `ShadowedName`)" # ArgParser.many <#> NonEmptySet.fromFoldable -psaFilterCodes :: ArgParser (Maybe (NonEmptySet String)) -psaFilterCodes = - ArgParser.argument [ "--psa-filter-code" ] +filterCodes :: ArgParser (Maybe (NonEmptySet String)) +filterCodes = + ArgParser.argument [ "---filter-code" ] "Only show a specific error code (e.g. `TypesDoNotUnify`)" # ArgParser.many <#> NonEmptySet.fromFoldable -psaStatVerbosity :: ArgParser (Maybe Core.StatVerbosity) -psaStatVerbosity = ArgParser.optional $ ArgParser.choose "StatVerbosity" - [ Core.VerboseStats <$ ArgParser.flag [ "--psa-verbose-stats" ] "Show counts for each warning type" - , Core.NoStats <$ ArgParser.flag [ "--psa-censor-stats" ] "Censor warning/error summary" +statVerbosity :: ArgParser (Maybe Core.StatVerbosity) +statVerbosity = ArgParser.optional $ ArgParser.choose "StatVerbosity" + [ Core.VerboseStats <$ ArgParser.flag [ "---verbose-stats" ] "Show counts for each warning type" + , Core.NoStats <$ ArgParser.flag [ "---censor-stats" ] "Censor warning/error summary" ] -psaStashFile ∷ ArgParser (Maybe (Either Boolean String)) -psaStashFile = ArgParser.optional $ ArgParser.choose "stash" - [ ArgParser.argument [ "--psa-stash-file" ] "Enable persistent warnings using a specific stash file" +stashFile ∷ ArgParser (Maybe (Either Boolean String)) +stashFile = ArgParser.optional $ ArgParser.choose "stash" + [ ArgParser.argument [ "---stash-file" ] "Enable persistent warnings using a specific stash file" # ArgParser.unformat "FILE" (Right <<< Right <<< Paths.mkLocalCachesCustomStashFile <<< Path.basename) - , Left true <$ ArgParser.flag [ "--psa-stash" ] "Enable persistent warnings using default stash file location" + , Left true <$ ArgParser.flag [ "---stash" ] "Enable persistent warnings using default stash file location" ] jsonErrors ∷ ArgParser Boolean diff --git a/spaghetto/bin/src/Main.purs b/spaghetto/bin/src/Main.purs index 6d42aa8fb..b37ac13b2 100644 --- a/spaghetto/bin/src/Main.purs +++ b/spaghetto/bin/src/Main.purs @@ -306,15 +306,15 @@ installArgsParser = psaArgsParser :: ArgParser PsaArgs psaArgsParser = ArgParser.fromRecord - { strict: Flags.psaStrict - , censorWarnings: Flags.psaCensorWarnings - , censorLib: Flags.psaCensorLib - , censorSrc: Flags.psaCensorSrc - , showSource: Flags.psaShowSource - , censorCodes: Flags.psaCensorCodes - , filterCodes: Flags.psaFilterCodes - , statVerbosity: Flags.psaStatVerbosity - , stashFile: Flags.psaStashFile + { strict: Flags.strict + , censorWarnings: Flags.censorWarnings + , censorLib: Flags.censorLib + , censorSrc: Flags.censorSrc + , showSource: Flags.showSource + , censorCodes: Flags.censorCodes + , filterCodes: Flags.filterCodes + , statVerbosity: Flags.statVerbosity + , stashFile: Flags.stashFile } buildArgsParser :: ArgParser (BuildArgs ()) From 3a8464557d875de68836d03e908cab99e0ab8836 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 6 Apr 2023 08:37:27 -0500 Subject: [PATCH 60/78] From jsonErrors from Install/Run/Test/Bundle Args --- spaghetto/bin/src/Main.purs | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/spaghetto/bin/src/Main.purs b/spaghetto/bin/src/Main.purs index b37ac13b2..bae6e10ed 100644 --- a/spaghetto/bin/src/Main.purs +++ b/spaghetto/bin/src/Main.purs @@ -72,7 +72,6 @@ type InstallArgs = , output :: Maybe String , pedanticPackages :: Boolean , ensureRanges :: Boolean - , jsonErrors :: Boolean , psaArgs :: PsaArgs } @@ -116,7 +115,6 @@ type RunArgs = , execArgs :: Maybe (Array String) , main :: Maybe String , ensureRanges :: Boolean - , jsonErrors :: Boolean , psaArgs :: PsaArgs } @@ -127,7 +125,6 @@ type TestArgs = , pursArgs :: List String , backendArgs :: List String , execArgs :: Maybe (Array String) - , jsonErrors :: Boolean , psaArgs :: PsaArgs } @@ -157,7 +154,6 @@ type BundleArgs = , pedanticPackages :: Boolean , type :: Maybe String , ensureRanges :: Boolean - , jsonErrors :: Boolean , psaArgs :: PsaArgs } @@ -300,7 +296,6 @@ installArgsParser = , output: Flags.output , pedanticPackages: Flags.pedanticPackages , ensureRanges: Flags.ensureRanges - , jsonErrors: Flags.jsonErrors , psaArgs: psaArgsParser } @@ -346,7 +341,6 @@ runArgsParser = ArgParser.fromRecord , pedanticPackages: Flags.pedanticPackages , main: Flags.moduleName , ensureRanges: Flags.ensureRanges - , jsonErrors: Flags.jsonErrors , psaArgs: psaArgsParser } @@ -358,7 +352,6 @@ testArgsParser = ArgParser.fromRecord , execArgs: Flags.execArgs , output: Flags.output , pedanticPackages: Flags.pedanticPackages - , jsonErrors: Flags.jsonErrors , psaArgs: psaArgsParser } @@ -376,7 +369,6 @@ bundleArgsParser = , output: Flags.output , pedanticPackages: Flags.pedanticPackages , ensureRanges: Flags.ensureRanges - , jsonErrors: Flags.jsonErrors , psaArgs: psaArgsParser } @@ -454,12 +446,12 @@ main = RegistryInfo args -> do env <- mkRegistryEnv void $ runSpago env (Registry.info args) - Install args@{ packages, selectedPackage, ensureRanges, jsonErrors } -> do + Install args@{ packages, selectedPackage, ensureRanges } -> do { env, fetchOpts } <- mkFetchEnv { packages, selectedPackage, ensureRanges } -- TODO: --no-fetch flag dependencies <- runSpago env (Fetch.run fetchOpts) env' <- runSpago env (mkBuildEnv args dependencies) - let options = { depsOnly: true, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors } + let options = { depsOnly: true, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors: false } runSpago env' (Build.run options) Build args@{ selectedPackage, ensureRanges, jsonErrors } -> do { env, fetchOpts } <- mkFetchEnv { packages: mempty, selectedPackage, ensureRanges } @@ -476,7 +468,7 @@ main = buildArgs = { selectedPackage , psaArgs - , pursArgs: mempty + -- , pursArgs: mempty , backendArgs: mempty , output: mempty , pedanticPackages: false @@ -489,33 +481,33 @@ main = Repl args -> do -- TODO implement pure unit - Bundle args@{ selectedPackage, ensureRanges, jsonErrors } -> do + Bundle args@{ selectedPackage, ensureRanges } -> do { env, fetchOpts } <- mkFetchEnv { packages: mempty, selectedPackage, ensureRanges } -- TODO: --no-fetch flag dependencies <- runSpago env (Fetch.run fetchOpts) -- TODO: --no-build flag buildEnv <- runSpago env (mkBuildEnv args dependencies) - let options = { depsOnly: false, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors } + let options = { depsOnly: false, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors: false } runSpago buildEnv (Build.run options) bundleEnv <- runSpago env (mkBundleEnv args) runSpago bundleEnv Bundle.run - Run args@{ selectedPackage, ensureRanges, jsonErrors } -> do + Run args@{ selectedPackage, ensureRanges } -> do { env, fetchOpts } <- mkFetchEnv { packages: mempty, selectedPackage, ensureRanges } -- TODO: --no-fetch flag dependencies <- runSpago env (Fetch.run fetchOpts) -- TODO: --no-build flag buildEnv <- runSpago env (mkBuildEnv args dependencies) - let options = { depsOnly: false, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors } + let options = { depsOnly: false, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors: false } runSpago buildEnv (Build.run options) runEnv <- runSpago env (mkRunEnv args) runSpago runEnv Run.run - Test args@{ selectedPackage, jsonErrors } -> do + Test args@{ selectedPackage } -> do { env, fetchOpts } <- mkFetchEnv { packages: mempty, selectedPackage, ensureRanges: false } -- TODO: --no-fetch flag dependencies <- runSpago env (Fetch.run fetchOpts) -- TODO: --no-build flag buildEnv <- runSpago env (mkBuildEnv (Record.union args { ensureRanges: false }) dependencies) - let options = { depsOnly: false, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors } + let options = { depsOnly: false, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors: false } runSpago buildEnv (Build.run options) testEnv <- runSpago env (mkTestEnv args) runSpago testEnv Test.run @@ -678,7 +670,16 @@ mkTestEnv testArgs = do let testEnv = { logOptions, workspace: newWorkspace, selectedPackages, node } pure testEnv -mkBuildEnv :: forall a b. BuildArgs b -> Map PackageName Package -> Spago (Fetch.FetchEnv a) (Build.BuildEnv ()) +mkBuildEnv + :: forall r + . { backendArgs :: List String + , output :: Maybe String + , pedanticPackages :: Boolean + , psaArgs :: PsaArgs + | r + } + -> Map PackageName Package + -> Spago (Fetch.FetchEnv ()) (Build.BuildEnv ()) mkBuildEnv buildArgs dependencies = do { logOptions, workspace, git } <- ask purs <- Purs.getPurs From e4b8442db6f96fc91da00932baa841fd1c51ebb3 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 6 Apr 2023 08:58:38 -0500 Subject: [PATCH 61/78] Merge 3 CLI args into 1 It doesn't make sense to use both `--censor-warnings` and `--censor-src`. --- spaghetto/bin/src/Flags.purs | 30 +++++++------------ spaghetto/bin/src/Main.purs | 12 ++------ spaghetto/core/src/Config.purs | 40 ++++++++++++++++++++++---- spaghetto/src/Spago/Command/Build.purs | 4 +-- spaghetto/src/Spago/Psa.purs | 12 ++------ spaghetto/src/Spago/Psa/Output.purs | 19 ++++++++++-- spaghetto/src/Spago/Psa/Types.purs | 4 +-- 7 files changed, 69 insertions(+), 52 deletions(-) diff --git a/spaghetto/bin/src/Flags.purs b/spaghetto/bin/src/Flags.purs index f9ff10841..796590b23 100644 --- a/spaghetto/bin/src/Flags.purs +++ b/spaghetto/bin/src/Flags.purs @@ -24,25 +24,17 @@ strict = # ArgParser.boolean # ArgParser.optional -censorWarnings ∷ ArgParser (Maybe Boolean) -censorWarnings = - ArgParser.flag [ "---censor-warnings" ] - "Censor all warnings" - # ArgParser.boolean - # ArgParser.optional - -censorLib ∷ ArgParser (Maybe Boolean) -censorLib = - ArgParser.flag [ "---censor-lib" ] - "Censor warnings from library sources" - # ArgParser.boolean - # ArgParser.optional - -censorSrc ∷ ArgParser (Maybe Boolean) -censorSrc = - ArgParser.flag [ "---censor-src" ] - "Censor warnings from project sources" - # ArgParser.boolean +censorBuildWarnings ∷ ArgParser (Maybe Core.CensorBuildWarnings) +censorBuildWarnings = + ArgParser.argument [ "---censor-build-warnings" ] + "Censor compiler warnings based on file's location: 'dependency', 'project', or 'all'" + # ArgParser.unformat "ARG" + ( case _ of + "all" -> Right Core.CensorAllWarnings + "project" -> Right Core.CensorProjectWarnings + "dependency" -> Right Core.CensorDependencyWarnings + _ -> Left $ "Expected 'all', 'project', or 'dependency'" + ) # ArgParser.optional showSource ∷ ArgParser (Maybe ShowSourceCode) diff --git a/spaghetto/bin/src/Main.purs b/spaghetto/bin/src/Main.purs index bae6e10ed..d043e0b0c 100644 --- a/spaghetto/bin/src/Main.purs +++ b/spaghetto/bin/src/Main.purs @@ -77,9 +77,7 @@ type InstallArgs = type PsaArgs = { strict :: Maybe Boolean - , censorWarnings :: Maybe Boolean - , censorLib :: Maybe Boolean - , censorSrc :: Maybe Boolean + , censorBuildWarnings :: Maybe Core.CensorBuildWarnings , showSource :: Maybe Core.ShowSourceCode , censorCodes :: Maybe (NonEmptySet String) , filterCodes :: Maybe (NonEmptySet String) @@ -302,9 +300,7 @@ installArgsParser = psaArgsParser :: ArgParser PsaArgs psaArgsParser = ArgParser.fromRecord { strict: Flags.strict - , censorWarnings: Flags.censorWarnings - , censorLib: Flags.censorLib - , censorSrc: Flags.censorSrc + , censorBuildWarnings: Flags.censorBuildWarnings , showSource: Flags.showSource , censorCodes: Flags.censorCodes , filterCodes: Flags.filterCodes @@ -701,9 +697,7 @@ mkBuildEnv buildArgs dependencies = do psaConfig :: Core.PsaConfig psaConfig = { strict: alt buildArgs.psaArgs.strict $ config >>= _.strict - , censorWarnings: alt buildArgs.psaArgs.censorWarnings $ config >>= _.censorWarnings - , censorLib: alt buildArgs.psaArgs.censorWarnings $ config >>= _.censorLib - , censorSrc: alt buildArgs.psaArgs.censorSrc $ config >>= _.censorSrc + , censorBuildWarnings: alt buildArgs.psaArgs.censorBuildWarnings $ config >>= _.censorBuildWarnings , showSource: alt buildArgs.psaArgs.showSource $ config >>= _.showSource , censorCodes: alt buildArgs.psaArgs.censorCodes $ config >>= _.censorCodes , filterCodes: alt buildArgs.psaArgs.filterCodes $ config >>= _.filterCodes diff --git a/spaghetto/core/src/Config.purs b/spaghetto/core/src/Config.purs index e880c133e..f29861589 100644 --- a/spaghetto/core/src/Config.purs +++ b/spaghetto/core/src/Config.purs @@ -3,6 +3,7 @@ module Spago.Core.Config , BuildOptionsInput , BuildConfig , PsaConfig + , CensorBuildWarnings(..) , ShowSourceCode(..) , StatVerbosity(..) , BundleConfig @@ -88,9 +89,7 @@ buildConfigCodec = CAR.object "BuildConfig" } type PsaConfig = - { censorWarnings :: Maybe Boolean - , censorLib :: Maybe Boolean - , censorSrc :: Maybe Boolean + { censorBuildWarnings :: Maybe CensorBuildWarnings , censorCodes :: Maybe (NonEmptySet.NonEmptySet String) , filterCodes :: Maybe (NonEmptySet.NonEmptySet String) , statVerbosity :: Maybe StatVerbosity @@ -101,9 +100,7 @@ type PsaConfig = psaConfigCodec :: JsonCodec PsaConfig psaConfigCodec = CAR.object "PsaConfig" - { censorWarnings: CAR.optional CA.boolean - , censorLib: CAR.optional CA.boolean - , censorSrc: CAR.optional CA.boolean + { censorBuildWarnings: CAR.optional censorBuildWarningsCodec , censorCodes: CAR.optional $ CA.Common.nonEmptySet CA.string , filterCodes: CAR.optional $ CA.Common.nonEmptySet CA.string , statVerbosity: CAR.optional statVerbosityCodec @@ -118,6 +115,37 @@ stashFileCodec = CA.Sum.enumSum (either show identity) case _ of "false" -> Just $ Left false x -> Just $ Right x +data CensorBuildWarnings + = CensorNoWarnings + | CensorDependencyWarnings + | CensorProjectWarnings + | CensorAllWarnings + +derive instance Eq CensorBuildWarnings + +instance Show CensorBuildWarnings where + show = case _ of + CensorNoWarnings -> "CensorNoWarnings" + CensorDependencyWarnings -> "CensorDependencyWarnings" + CensorProjectWarnings -> "CensorProjectWarnings" + CensorAllWarnings -> "CensorAllWarnings" + +censorBuildWarningsCodec :: JsonCodec CensorBuildWarnings +censorBuildWarningsCodec = CA.Sum.enumSum print parse + where + print = case _ of + CensorNoWarnings -> "none" + CensorDependencyWarnings -> "dependency" + CensorProjectWarnings -> "project" + CensorAllWarnings -> "all" + + parse = case _ of + "none" -> Just CensorNoWarnings + "dependency" -> Just CensorDependencyWarnings + "project" -> Just CensorProjectWarnings + "all" -> Just CensorAllWarnings + _ -> Nothing + data ShowSourceCode = ShowSourceCode | NoSourceCode diff --git a/spaghetto/src/Spago/Command/Build.purs b/spaghetto/src/Spago/Command/Build.purs index 8d4cb9953..1ceb00750 100644 --- a/spaghetto/src/Spago/Command/Build.purs +++ b/spaghetto/src/Spago/Command/Build.purs @@ -93,9 +93,7 @@ run opts = do Nothing -> Just Paths.localCachesStashEntireWorkspace psaOptions = { strict: fromMaybe Psa.defaultParseOptions.strict psaConfig.strict - , censorWarnings: fromMaybe Psa.defaultParseOptions.censorWarnings psaConfig.censorWarnings - , censorLib: fromMaybe Psa.defaultParseOptions.censorLib psaConfig.censorLib - , censorSrc: fromMaybe Psa.defaultParseOptions.censorSrc psaConfig.censorSrc + , censorBuildWarnings: fromMaybe Psa.defaultParseOptions.censorBuildWarnings psaConfig.censorBuildWarnings , showSource: fromMaybe Psa.defaultParseOptions.showSource psaConfig.showSource , censorCodes: maybe Psa.defaultParseOptions.censorCodes NonEmptySet.toSet psaConfig.censorCodes , filterCodes: maybe Psa.defaultParseOptions.filterCodes NonEmptySet.toSet psaConfig.filterCodes diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index 55afd8fc1..d388cf052 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -43,9 +43,7 @@ defaultParseOptions :: PsaOptions defaultParseOptions = { showSource: Core.ShowSourceCode , stashFile: Nothing - , censorWarnings: false - , censorLib: false - , censorSrc: false + , censorBuildWarnings: Core.CensorNoWarnings , censorCodes: Set.empty , filterCodes: Set.empty , statVerbosity: Core.CompactStats @@ -55,9 +53,7 @@ defaultParseOptions = type PsaOptions = { showSource :: Core.ShowSourceCode , stashFile :: Maybe String - , censorWarnings :: Boolean - , censorLib :: Boolean - , censorSrc :: Boolean + , censorBuildWarnings :: Core.CensorBuildWarnings , censorCodes :: Set ErrorCode , filterCodes :: Set ErrorCode , statVerbosity :: Core.StatVerbosity @@ -67,9 +63,7 @@ type PsaOptions = toOutputOptions :: PsaArgs -> PsaOptions -> PsaOutputOptions toOutputOptions { libraryDirs, color } options = { color - , censorWarnings: options.censorWarnings - , censorLib: options.censorLib - , censorSrc: options.censorSrc + , censorBuildWarnings: options.censorBuildWarnings , censorCodes: options.censorCodes , filterCodes: options.filterCodes , statVerbosity: options.statVerbosity diff --git a/spaghetto/src/Spago/Psa/Output.purs b/spaghetto/src/Spago/Psa/Output.purs index df95b1bd8..181906be3 100644 --- a/spaghetto/src/Spago/Psa/Output.purs +++ b/spaghetto/src/Spago/Psa/Output.purs @@ -23,6 +23,8 @@ import Data.String as Str import Data.Tuple (Tuple(..)) import Foreign.Object as FO import Node.Path as Path +import Spago.Core.Config (CensorBuildWarnings(..)) +import Spago.Core.Config as Core import Spago.Paths as Paths import Spago.Psa.Types (PsaOutputOptions, PsaError, PsaAnnotedError, PsaPath(..), PsaResult, Position, Filename, Lines, compareByLocation) @@ -146,11 +148,22 @@ updateStats tag path code printed s = alterStat Nothing = Just (bump (Tuple 0 0)) alterStat (Just x) = Just (bump x) +censorSrc :: Core.CensorBuildWarnings -> Boolean +censorSrc = case _ of + CensorAllWarnings -> true + CensorProjectWarnings -> true + _ -> false + +censorLib :: Core.CensorBuildWarnings -> Boolean +censorLib = case _ of + CensorAllWarnings -> true + CensorProjectWarnings -> true + _ -> false + shouldShowError :: PsaOutputOptions -> ErrorTag -> PsaPath -> String -> Boolean shouldShowError _ Error _ _ = true -shouldShowError { filterCodes, censorCodes, censorSrc, censorLib, censorWarnings } _ path code = - not censorWarnings - && not (censorSrc && isSrc path || censorLib && isLib path) +shouldShowError { filterCodes, censorCodes, censorBuildWarnings } _ path code = + not (censorSrc censorBuildWarnings && isSrc path || censorLib censorBuildWarnings && isLib path) && (Set.isEmpty filterCodes || Set.member code filterCodes) && (Set.isEmpty censorCodes || not (Set.member code censorCodes)) diff --git a/spaghetto/src/Spago/Psa/Types.purs b/spaghetto/src/Spago/Psa/Types.purs index 5ca42f5a4..26e3bf87d 100644 --- a/spaghetto/src/Spago/Psa/Types.purs +++ b/spaghetto/src/Spago/Psa/Types.purs @@ -51,9 +51,7 @@ derive instance Ord PsaPath type PsaOutputOptions = { color :: Boolean - , censorWarnings :: Boolean - , censorLib :: Boolean - , censorSrc :: Boolean + , censorBuildWarnings :: Core.CensorBuildWarnings , censorCodes :: Set ErrorCode , filterCodes :: Set ErrorCode , statVerbosity :: Core.StatVerbosity From a38eb017b7f9e0cc307cc6053eef1f906a482ccb Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 6 Apr 2023 09:04:16 -0500 Subject: [PATCH 62/78] Add missing value demoing custom stash file --- spaghetto/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spaghetto/README.md b/spaghetto/README.md index d87037db2..9e64ecf3b 100644 --- a/spaghetto/README.md +++ b/spaghetto/README.md @@ -284,6 +284,7 @@ package: # 2. Enable it using default location (.spago/default/) true # 3. Enable it using custom location (.spago/custom) + "foo" # optional bundle: From c4bcd5c9eecb3cbabba1a8496bf2b8bf102db145 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 6 Apr 2023 09:05:43 -0500 Subject: [PATCH 63/78] Update comment to refer to json errors, not output --- spaghetto/src/Spago/Command/Build.purs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spaghetto/src/Spago/Command/Build.purs b/spaghetto/src/Spago/Command/Build.purs index 1ceb00750..4e0bab4d6 100644 --- a/spaghetto/src/Spago/Command/Build.purs +++ b/spaghetto/src/Spago/Command/Build.purs @@ -75,7 +75,7 @@ run opts = do Nothing -> args Just output -> args <> [ "--output", output ] - -- find the output flag and die if it's there - Spago handles it + -- find the `--json-errors` flag and die if it's there - Spago handles it when (isJust $ Cmd.findFlag { flags: [ "--json-errors" ], args: opts.pursArgs }) do die [ "Can't pass `--json-errors` option directly to purs." From 1d24ed4126f1c41d746c673a0ac221ba6a65dec8 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 6 Apr 2023 09:08:41 -0500 Subject: [PATCH 64/78] Decoding psaaResult codec error should not fail build --- spaghetto/src/Spago/Psa.purs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index d388cf052..f33ddfa27 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -86,13 +86,13 @@ psaCompile globs pursArgs psaArgs options@{ showSource, stashFile } = do arrErrorsIsEmpty <- forWithIndex (Str.split (Str.Pattern "\n") result'.output) \idx err -> case jsonParser err >>= CA.decode psaResultCodec >>> lmap CA.printJsonDecodeError of Left decodeErrMsg -> do - logDebug $ Array.intercalate "\n" + logWarn $ Array.intercalate "\n" [ "Failed to decode PsaResult at index '" <> show idx <> "': " <> decodeErrMsg , "Json was: " <> err ] - -- Note to reviewer: - -- Should a stash decode error cause a non-zero exit? - pure false + -- If we can't decode the error, then there's likely a codec issue on Spago's side. + -- So, this shouldn't fail the build. + pure true Right out -> do files <- liftEffect $ Ref.new FO.empty let From 01664cee51ecf61424ff718c53125caf2e8ea339 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 6 Apr 2023 09:10:14 -0500 Subject: [PATCH 65/78] Rename DefaultPrinter as just Printer --- spaghetto/src/Spago/Psa.purs | 2 +- spaghetto/src/Spago/Psa/{Printer/Default.purs => Printer.purs} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename spaghetto/src/Spago/Psa/{Printer/Default.purs => Printer.purs} (99%) diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index f33ddfa27..eadf1258a 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -28,7 +28,7 @@ import Node.FS.Sync as FSSync import Node.Path (dirname) import Spago.Core.Config as Core import Spago.Psa.Output (buildOutput) -import Spago.Psa.Printer.Default as DefaultPrinter +import Spago.Psa.Printer as DefaultPrinter import Spago.Psa.Printer.Json as JsonPrinter import Spago.Psa.Types (PsaOutputOptions, ErrorCode, psaErrorCodec, psaResultCodec) import Spago.Purs as Purs diff --git a/spaghetto/src/Spago/Psa/Printer/Default.purs b/spaghetto/src/Spago/Psa/Printer.purs similarity index 99% rename from spaghetto/src/Spago/Psa/Printer/Default.purs rename to spaghetto/src/Spago/Psa/Printer.purs index e6a0a7cd0..7a8683047 100644 --- a/spaghetto/src/Spago/Psa/Printer/Default.purs +++ b/spaghetto/src/Spago/Psa/Printer.purs @@ -4,7 +4,7 @@ -- To fullfil license requirements -- Copyright © Nathan Faubion -- https://opensource.org/license/mit/ -module Spago.Psa.Printer.Default +module Spago.Psa.Printer ( renderWarning , renderError , renderStats From f4f585aeddbba3a709d9a0e5cc718cc7544842a2 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 6 Apr 2023 09:13:39 -0500 Subject: [PATCH 66/78] Inline json printer into Printer Long names are used here to prevent a clash with Spago.Prelude's `printJson`. --- spaghetto/src/Spago/Psa.purs | 5 ++--- spaghetto/src/Spago/Psa/Printer.purs | 21 +++++++++++++++++---- spaghetto/src/Spago/Psa/Printer/Json.purs | 22 ---------------------- 3 files changed, 19 insertions(+), 29 deletions(-) delete mode 100644 spaghetto/src/Spago/Psa/Printer/Json.purs diff --git a/spaghetto/src/Spago/Psa.purs b/spaghetto/src/Spago/Psa.purs index eadf1258a..be916418e 100644 --- a/spaghetto/src/Spago/Psa.purs +++ b/spaghetto/src/Spago/Psa.purs @@ -28,8 +28,7 @@ import Node.FS.Sync as FSSync import Node.Path (dirname) import Spago.Core.Config as Core import Spago.Psa.Output (buildOutput) -import Spago.Psa.Printer as DefaultPrinter -import Spago.Psa.Printer.Json as JsonPrinter +import Spago.Psa.Printer (printDefaultOutputToErr, printJsonOutputToOut) import Spago.Psa.Types (PsaOutputOptions, ErrorCode, psaErrorCodec, psaResultCodec) import Spago.Purs as Purs @@ -103,7 +102,7 @@ psaCompile globs pursArgs psaArgs options@{ showSource, stashFile } = do out' <- buildOutput loadLinesImpl outputOptions out { warnings = merged } - liftEffect $ if psaArgs.jsonErrors then JsonPrinter.print out' else DefaultPrinter.print outputOptions out' + liftEffect $ if psaArgs.jsonErrors then printJsonOutputToOut out' else printDefaultOutputToErr outputOptions out' pure $ FO.isEmpty out'.stats.allErrors diff --git a/spaghetto/src/Spago/Psa/Printer.purs b/spaghetto/src/Spago/Psa/Printer.purs index 7a8683047..3a57ad2c6 100644 --- a/spaghetto/src/Spago/Psa/Printer.purs +++ b/spaghetto/src/Spago/Psa/Printer.purs @@ -9,14 +9,17 @@ module Spago.Psa.Printer , renderError , renderStats , renderVerboseStats - , print + , printDefaultOutputToErr + , printJsonOutputToOut ) where import Prelude import Ansi.Codes as Ansi import Control.Alternative as Alternative +import Data.Argonaut.Core (stringify) import Data.Array as Array +import Data.Codec.Argonaut as CA import Data.Foldable (fold, foldMap, maximum, maximumBy) import Data.FoldableWithIndex (forWithIndex_) import Data.Maybe (Maybe(..), fromMaybe, maybe) @@ -31,11 +34,21 @@ import Effect.Console as Console import Foreign.Object as FO import Spago.Core.Config as Core import Spago.Psa.Output (OutputStats, Output) -import Spago.Psa.Types (Lines, Position, PsaAnnotedError, PsaOutputOptions, PsaPath(..)) +import Spago.Psa.Types (Lines, Position, PsaAnnotedError, PsaOutputOptions, PsaPath(..), psaResultCodec) + +printJsonOutputToOut :: Output -> Effect Unit +printJsonOutputToOut output = do + let + result = CA.encode psaResultCodec + { warnings: _.error <$> output.warnings + , errors: _.error <$> output.errors + } + + Console.log (stringify result) -- | Prints output to the console. -print :: PsaOutputOptions -> Output -> Effect Unit -print options output = do +printDefaultOutputToErr :: PsaOutputOptions -> Output -> Effect Unit +printDefaultOutputToErr options output = do forWithIndex_ output.warnings \i warning -> do Console.error $ printDoc (renderWarning lenWarnings (i + 1) warning) Console.error "" diff --git a/spaghetto/src/Spago/Psa/Printer/Json.purs b/spaghetto/src/Spago/Psa/Printer/Json.purs deleted file mode 100644 index 5869fe32f..000000000 --- a/spaghetto/src/Spago/Psa/Printer/Json.purs +++ /dev/null @@ -1,22 +0,0 @@ -module Spago.Psa.Printer.Json - ( print - ) where - -import Prelude - -import Data.Argonaut.Core (stringify) -import Data.Codec.Argonaut as CA -import Effect (Effect) -import Effect.Console as Console -import Spago.Psa.Output (Output) -import Spago.Psa.Types (psaResultCodec) - -print :: Output -> Effect Unit -print output = do - let - result = CA.encode psaResultCodec - { warnings: _.error <$> output.warnings - , errors: _.error <$> output.errors - } - - Console.log (stringify result) From 3a4451f20c525562c279cfede8fb9a08142f287d Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 6 Apr 2023 09:41:08 -0500 Subject: [PATCH 67/78] Revert sourceGlob' change --- spaghetto/src/Spago/Command/Build.purs | 23 +++++++++++++---------- spaghetto/src/Spago/Config.purs | 25 ++++++++----------------- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/spaghetto/src/Spago/Command/Build.purs b/spaghetto/src/Spago/Command/Build.purs index 4e0bab4d6..0e6c14dfc 100644 --- a/spaghetto/src/Spago/Command/Build.purs +++ b/spaghetto/src/Spago/Command/Build.purs @@ -14,7 +14,7 @@ import Data.Tuple as Tuple import Registry.PackageName as PackageName import Spago.BuildInfo as BuildInfo import Spago.Cmd as Cmd -import Spago.Config (Package(..), WithTestGlobs(..), Workspace, WorkspacePackage, PsaConfig) +import Spago.Config (Package(..), PsaConfig, WithTestGlobs(..), Workspace, WorkspacePackage) import Spago.Config as Config import Spago.Git (Git) import Spago.Paths as Paths @@ -43,15 +43,18 @@ run opts = do logInfo "Building..." { dependencies, workspace, logOptions, psaConfig } <- ask let + isWorkspacePackage = case _ of + Tuple _ (WorkspacePackage _) -> true + _ -> false + + { yes: monorepoPkgs, no: dependencyPkgs } = partition isWorkspacePackage $ Map.toUnfoldable dependencies -- depsOnly means "no packages from the monorepo", so we filter out the workspace packages - Tuple dependencyLibs dependencyGlobs = Array.unzip $ (Tuple.uncurry $ Config.sourceGlob' WithTestGlobs) =<< case opts.depsOnly of - false -> Map.toUnfoldable dependencies - true -> Map.toUnfoldable $ Map.filter - ( case _ of - WorkspacePackage _ -> false - _ -> true - ) - dependencies + dependencyGlobs = (Tuple.uncurry $ Config.sourceGlob WithTestGlobs) =<< dependencyPkgs + monorepoPkgGlobs + | opts.depsOnly = [] + | otherwise = (Tuple.uncurry $ Config.sourceGlob WithTestGlobs) =<< monorepoPkgs + + dependencyLibs = map (Tuple.uncurry Config.getPackageLocation) dependencyPkgs -- Here we select the right globs for a monorepo setup with a bunch of packages projectSources = join @@ -141,7 +144,7 @@ run opts = do runCommands "Then" thenCommands -} - let globs = Set.fromFoldable $ projectSources <> dependencyGlobs <> [ BuildInfo.buildInfoPath ] + let globs = Set.fromFoldable $ projectSources <> monorepoPkgGlobs <> dependencyGlobs <> [ BuildInfo.buildInfoPath ] buildBackend globs when workspace.buildOptions.pedanticPackages do diff --git a/spaghetto/src/Spago/Config.purs b/spaghetto/src/Spago/Config.purs index 029bcac0f..0d7f1c46c 100644 --- a/spaghetto/src/Spago/Config.purs +++ b/spaghetto/src/Spago/Config.purs @@ -12,7 +12,6 @@ module Spago.Config , getWorkspacePackages , readWorkspace , sourceGlob - , sourceGlob' , module Core ) where @@ -325,10 +324,7 @@ data WithTestGlobs | OnlyTestGlobs sourceGlob :: WithTestGlobs -> PackageName -> Package -> Array String -sourceGlob withTestGlobs name package = map snd $ sourceGlob' withTestGlobs name package - -sourceGlob' :: WithTestGlobs -> PackageName -> Package -> Array (Tuple String String) -sourceGlob' withTestGlobs name package = +sourceGlob withTestGlobs name package = map (\p -> Path.concat [ getPackageLocation name package, p ]) case package of WorkspacePackage { hasTests } -> case hasTests, withTestGlobs of @@ -337,19 +333,14 @@ sourceGlob' withTestGlobs name package = true, OnlyTestGlobs -> [ testGlob ] true, NoTestGlobs -> [ srcGlob ] true, WithTestGlobs -> [ srcGlob, testGlob ] - GitPackage { subdir: Just s } -> [ subdirSrcGlob s ] + GitPackage { subdir: Just s } -> [ Path.concat [ s, srcGlob ] ] _ -> [ srcGlob ] - where - pkgLocation = getPackageLocation name package - srcGlob = Tuple - (Path.concat [ pkgLocation, "src" ]) - (Path.concat [ pkgLocation, "src/**/*.purs" ]) - subdirSrcGlob subdir = Tuple - (Path.concat [ pkgLocation, subdir, "src" ]) - (Path.concat [ pkgLocation, subdir, "src/**/*.purs" ]) - testGlob = Tuple - (Path.concat [ pkgLocation, "test" ]) - (Path.concat [ pkgLocation, "test/**/*.purs" ]) + +srcGlob :: String +srcGlob = "src/**/*.purs" + +testGlob :: String +testGlob = "test/**/*.purs" getWorkspacePackages :: PackageSet -> Array WorkspacePackage getWorkspacePackages = Array.mapMaybe extractWorkspacePackage <<< Map.toUnfoldable From 92dbed1bbcfd66d8eb251cad408b2fbb126a2518 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 19 Apr 2023 09:11:16 -0500 Subject: [PATCH 68/78] Remove custom stash file locations; rename to stash --- spaghetto/README.md | 13 ++----------- spaghetto/bin/src/Flags.purs | 13 +++++-------- spaghetto/bin/src/Main.purs | 6 +++--- spaghetto/core/src/Config.purs | 10 ++-------- spaghetto/src/Spago/Command/Build.purs | 12 +++++------- spaghetto/src/Spago/Paths.purs | 15 +++------------ 6 files changed, 20 insertions(+), 49 deletions(-) diff --git a/spaghetto/README.md b/spaghetto/README.md index 9e64ecf3b..d2f05cd4e 100644 --- a/spaghetto/README.md +++ b/spaghetto/README.md @@ -274,17 +274,8 @@ package: showSource: true # optional, boolean, counts compiler warnings as compiler errors strict: false - # optional, Either Boolean String, enable/disable - # the pretty-printed compiler warnings/errors - # and whether to store them in a non-default location - stashFile: - # one of 3 values - # 1. Disable it - false - # 2. Enable it using default location (.spago/default/) - true - # 3. Enable it using custom location (.spago/custom) - "foo" + # optional, Boolean String, persist compiler warnings + stash: true # optional bundle: diff --git a/spaghetto/bin/src/Flags.purs b/spaghetto/bin/src/Flags.purs index 796590b23..29a816d0e 100644 --- a/spaghetto/bin/src/Flags.purs +++ b/spaghetto/bin/src/Flags.purs @@ -6,10 +6,8 @@ import ArgParse.Basic (ArgParser) import ArgParse.Basic as ArgParser import Data.Set.NonEmpty (NonEmptySet) import Data.Set.NonEmpty as NonEmptySet -import Node.Path as Path import Spago.Core.Config (ShowSourceCode(..)) import Spago.Core.Config as Core -import Spago.Paths as Paths selectedPackage ∷ ArgParser (Maybe String) selectedPackage = @@ -64,12 +62,11 @@ statVerbosity = ArgParser.optional $ ArgParser.choose "StatVerbosity" , Core.NoStats <$ ArgParser.flag [ "---censor-stats" ] "Censor warning/error summary" ] -stashFile ∷ ArgParser (Maybe (Either Boolean String)) -stashFile = ArgParser.optional $ ArgParser.choose "stash" - [ ArgParser.argument [ "---stash-file" ] "Enable persistent warnings using a specific stash file" - # ArgParser.unformat "FILE" (Right <<< Right <<< Paths.mkLocalCachesCustomStashFile <<< Path.basename) - , Left true <$ ArgParser.flag [ "---stash" ] "Enable persistent warnings using default stash file location" - ] +stash ∷ ArgParser (Maybe Boolean) +stash = + ArgParser.flag [ "---stash" ] "Enable persistent warnings using default stash file location" + # ArgParser.boolean + # ArgParser.optional jsonErrors ∷ ArgParser Boolean jsonErrors = diff --git a/spaghetto/bin/src/Main.purs b/spaghetto/bin/src/Main.purs index d043e0b0c..fae00d47b 100644 --- a/spaghetto/bin/src/Main.purs +++ b/spaghetto/bin/src/Main.purs @@ -82,7 +82,7 @@ type PsaArgs = , censorCodes :: Maybe (NonEmptySet String) , filterCodes :: Maybe (NonEmptySet String) , statVerbosity :: Maybe Core.StatVerbosity - , stashFile :: Maybe (Either Boolean String) + , stash :: Maybe Boolean } type BuildArgs a = @@ -305,7 +305,7 @@ psaArgsParser = ArgParser.fromRecord , censorCodes: Flags.censorCodes , filterCodes: Flags.filterCodes , statVerbosity: Flags.statVerbosity - , stashFile: Flags.stashFile + , stash: Flags.stash } buildArgsParser :: ArgParser (BuildArgs ()) @@ -702,7 +702,7 @@ mkBuildEnv buildArgs dependencies = do , censorCodes: alt buildArgs.psaArgs.censorCodes $ config >>= _.censorCodes , filterCodes: alt buildArgs.psaArgs.filterCodes $ config >>= _.filterCodes , statVerbosity: alt buildArgs.psaArgs.statVerbosity $ config >>= _.statVerbosity - , stashFile: alt buildArgs.psaArgs.stashFile $ config >>= _.stashFile + , stash: alt buildArgs.psaArgs.stash $ config >>= _.stash } where config :: Maybe Core.PsaConfig diff --git a/spaghetto/core/src/Config.purs b/spaghetto/core/src/Config.purs index f29861589..d5fab0b86 100644 --- a/spaghetto/core/src/Config.purs +++ b/spaghetto/core/src/Config.purs @@ -95,7 +95,7 @@ type PsaConfig = , statVerbosity :: Maybe StatVerbosity , showSource :: Maybe ShowSourceCode , strict :: Maybe Boolean - , stashFile :: Maybe (Either Boolean String) + , stash :: Maybe Boolean } psaConfigCodec :: JsonCodec PsaConfig @@ -106,15 +106,9 @@ psaConfigCodec = CAR.object "PsaConfig" , statVerbosity: CAR.optional statVerbosityCodec , showSource: CAR.optional showSourceCodec , strict: CAR.optional CA.boolean - , stashFile: CAR.optional stashFileCodec + , stash: CAR.optional CA.boolean } -stashFileCodec :: JsonCodec (Either Boolean String) -stashFileCodec = CA.Sum.enumSum (either show identity) case _ of - "true" -> Just $ Left true - "false" -> Just $ Left false - x -> Just $ Right x - data CensorBuildWarnings = CensorNoWarnings | CensorDependencyWarnings diff --git a/spaghetto/src/Spago/Command/Build.purs b/spaghetto/src/Spago/Command/Build.purs index 0e6c14dfc..d2afab994 100644 --- a/spaghetto/src/Spago/Command/Build.purs +++ b/spaghetto/src/Spago/Command/Build.purs @@ -91,9 +91,6 @@ run opts = do , color: logOptions.color , jsonErrors: opts.jsonErrors } - stashFileFallback = case workspace.selected of - Just p -> Just $ Paths.mkLocalCachesDefaultStashFile $ PackageName.print p.package.name - Nothing -> Just Paths.localCachesStashEntireWorkspace psaOptions = { strict: fromMaybe Psa.defaultParseOptions.strict psaConfig.strict , censorBuildWarnings: fromMaybe Psa.defaultParseOptions.censorBuildWarnings psaConfig.censorBuildWarnings @@ -103,10 +100,11 @@ run opts = do , statVerbosity: fromMaybe Psa.defaultParseOptions.statVerbosity psaConfig.statVerbosity , stashFile: do Alternative.guard (not opts.depsOnly) - psaConfig.stashFile >>= case _ of - Left true -> stashFileFallback - Left false -> Nothing - Right f -> Just f + stash <- psaConfig.stash + Alternative.guard stash + case workspace.selected of + Just p -> Just $ Paths.mkLocalCachesStashFile $ PackageName.print p.package.name + Nothing -> Just Paths.localCachesStashEntireWorkspace } buildBackend globs = do case workspace.backend of diff --git a/spaghetto/src/Spago/Paths.purs b/spaghetto/src/Spago/Paths.purs index 688cf743c..3d072ddc0 100644 --- a/spaghetto/src/Spago/Paths.purs +++ b/spaghetto/src/Spago/Paths.purs @@ -40,17 +40,8 @@ registryIndexPath = Path.concat [ globalCachePath, "registry-index" ] localCacheStashesPath :: FilePath localCacheStashesPath = Path.concat [ localCachePath, "stashes" ] -localCacheStashesDefaultsPath :: FilePath -localCacheStashesDefaultsPath = Path.concat [ localCacheStashesPath, "defaults" ] - -localCacheStashesCustomPath :: FilePath -localCacheStashesCustomPath = Path.concat [ localCacheStashesPath, "custom" ] - localCachesStashEntireWorkspace :: FilePath -localCachesStashEntireWorkspace = mkLocalCachesDefaultStashFile "entire-workspace" - -mkLocalCachesDefaultStashFile :: String -> FilePath -mkLocalCachesDefaultStashFile fileName = Path.concat [ localCacheStashesDefaultsPath, fileName <> ".stash" ] +localCachesStashEntireWorkspace = mkLocalCachesStashFile "entire-workspace" -mkLocalCachesCustomStashFile :: String -> FilePath -mkLocalCachesCustomStashFile fileName = Path.concat [ localCacheStashesCustomPath, fileName <> ".stash" ] +mkLocalCachesStashFile :: String -> FilePath +mkLocalCachesStashFile fileName = Path.concat [ localCacheStashesPath, fileName <> ".stash" ] From 83156572ee0830d1ccecbe0ae7b9fa1bf3ec01dd Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 19 Apr 2023 10:52:26 -0500 Subject: [PATCH 69/78] Update precedence: CLI > package > workspace > defaults --- spaghetto/README.md | 3 +-- spaghetto/bin/src/Main.purs | 33 +++++++++++++++++++++------------ 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/spaghetto/README.md b/spaghetto/README.md index d2f05cd4e..8d4cd8ecb 100644 --- a/spaghetto/README.md +++ b/spaghetto/README.md @@ -380,8 +380,7 @@ workspace: # optional, Boolean, fail the build if `spago.yml` has redundant/missing packages pedantic_packages: false # optional, PsaOptions - # These options only take affect when - # a package is not selected (e.g. `spago build` vs `spago build -p pkgName`) + # These options apply when a package does not specify the same value. psaOptions: # see the Package's `psaOptions` field ``` diff --git a/spaghetto/bin/src/Main.purs b/spaghetto/bin/src/Main.purs index fae00d47b..30bd660c4 100644 --- a/spaghetto/bin/src/Main.purs +++ b/spaghetto/bin/src/Main.purs @@ -4,10 +4,10 @@ import Spago.Prelude import ArgParse.Basic (ArgParser) import ArgParse.Basic as ArgParser -import Control.Alt (alt) import Data.Array as Array import Data.Array.NonEmpty as NonEmptyArray import Data.Codec.Argonaut.Common as CA.Common +import Data.Foldable (oneOf) import Data.JSDate as JSDate import Data.List as List import Data.Map as Map @@ -46,6 +46,7 @@ import Spago.Log (LogVerbosity(..)) import Spago.Paths as Paths import Spago.Purs (Purs) import Spago.Purs as Purs +import Type.Proxy (Proxy(..)) import Unsafe.Coerce (unsafeCoerce) type GlobalArgs = @@ -696,19 +697,27 @@ mkBuildEnv buildArgs dependencies = do psaConfig :: Core.PsaConfig psaConfig = - { strict: alt buildArgs.psaArgs.strict $ config >>= _.strict - , censorBuildWarnings: alt buildArgs.psaArgs.censorBuildWarnings $ config >>= _.censorBuildWarnings - , showSource: alt buildArgs.psaArgs.showSource $ config >>= _.showSource - , censorCodes: alt buildArgs.psaArgs.censorCodes $ config >>= _.censorCodes - , filterCodes: alt buildArgs.psaArgs.filterCodes $ config >>= _.filterCodes - , statVerbosity: alt buildArgs.psaArgs.statVerbosity $ config >>= _.statVerbosity - , stash: alt buildArgs.psaArgs.stash $ config >>= _.stash + { strict: getField $ Record.get (Proxy :: Proxy "strict") + , censorBuildWarnings: getField $ Record.get (Proxy :: Proxy "censorBuildWarnings") + , showSource: getField $ Record.get (Proxy :: Proxy "showSource") + , censorCodes: getField $ Record.get (Proxy :: Proxy "censorCodes") + , filterCodes: getField $ Record.get (Proxy :: Proxy "filterCodes") + , statVerbosity: getField $ Record.get (Proxy :: Proxy "statVerbosity") + , stash: getField $ Record.get (Proxy :: Proxy "stash") } where - config :: Maybe Core.PsaConfig - config = case workspace.selected of - Just p -> p.package.build >>= _.psaOptions - Nothing -> workspace.buildOptions.psaOptions + getField :: forall a. (Core.PsaConfig -> Maybe a) -> Maybe a + getField getLabel = oneOf + [ getLabel buildArgs.psaArgs + , packagePsaConfig >>= getLabel + , workspacePsaConfig >>= getLabel + ] + + packagePsaConfig :: Maybe Core.PsaConfig + packagePsaConfig = workspace.selected >>= \p -> p.package.build >>= _.psaOptions + + workspacePsaConfig :: Maybe Core.PsaConfig + workspacePsaConfig = workspace.buildOptions.psaOptions pure { logOptions, purs, git, dependencies, workspace: newWorkspace, psaConfig } From 52bda751260adc85f4ea045010ca8a17efdbf1bc Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 19 Apr 2023 10:56:06 -0500 Subject: [PATCH 70/78] Add comment explaining why stdout is not piped --- spaghetto/src/Spago/Purs.purs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spaghetto/src/Spago/Purs.purs b/spaghetto/src/Spago/Purs.purs index e7fc7f25f..5c7ca22d9 100644 --- a/spaghetto/src/Spago/Purs.purs +++ b/spaghetto/src/Spago/Purs.purs @@ -47,6 +47,11 @@ compile globs pursArgs = do { purs } <- ask let args = [ "compile" ] <> pursArgs <> Set.toUnfoldable globs logDebug [ "Running command:", "purs " <> String.joinWith " " args ] + -- PureScript (as of v0.14.0) outputs the compiler errors/warnings to `stdout` + -- and outputs "Compiling..." messages to `stderr` + -- So, we want to pipe stderr to the parent so we see the "Compiling..." messages in real-time. + -- However, we do not pipe `stdout` to the parent, so that we don't see the errors reported twice: + -- once via `purs` and once via spago's pretty-printing of the same errors/warnings. Cmd.exec purs.cmd args $ Cmd.defaultExecOptions { pipeStdout = false } From 136eb8ae73f9e1b5786f67dfef1ad85e1cf8bffc Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 19 Apr 2023 12:25:23 -0500 Subject: [PATCH 71/78] Unnest PSA options under `psa` field --- spaghetto/README.md | 68 +++++---- spaghetto/bin/src/Main.purs | 175 +++++++++++++++-------- spaghetto/core/src/Config.purs | 46 +++--- spaghetto/src/Spago/Command/Build.purs | 40 ++++-- spaghetto/src/Spago/Command/Init.purs | 8 +- spaghetto/src/Spago/Command/Publish.purs | 58 ++++++-- spaghetto/src/Spago/Config.purs | 17 ++- 7 files changed, 278 insertions(+), 134 deletions(-) diff --git a/spaghetto/README.md b/spaghetto/README.md index 8d4cd8ecb..5e17ede09 100644 --- a/spaghetto/README.md +++ b/spaghetto/README.md @@ -245,37 +245,35 @@ package: # optional build: - # optional - psaOptions: - # optional, Boolean, censor all warnings - censorWarnings: false - # optional, Boolean, censor warnings from library sources - censorLib: false - # optional, Boolean, censor warnings from project sources - censorSrc: false - # optional, NonEmptyArray, censor specific codes - censorCodes: - - ShadowedName - # optional, NonEmptyArray, only show specific codes - filterCodes: - - ShadowedName - # optional, whether to show statistics at the end - # of warning/error output and how much informaiton - statVerbosity: - # One of 3 values - # 1. Don't show it - "no-stats" - # 2. Show it and only sum the total warnings/errors - "compact-stats" - # 3. Show it and show total warnings/errors by code - "verbose-stats" - # optional, boolean, whether to show the source code - # corresponding to the error's location - showSource: true - # optional, boolean, counts compiler warnings as compiler errors - strict: false - # optional, Boolean String, persist compiler warnings - stash: true + # optional, Boolean, censor all warnings + censorWarnings: false + # optional, Boolean, censor warnings from library sources + censorLib: false + # optional, Boolean, censor warnings from project sources + censorSrc: false + # optional, NonEmptyArray, censor specific codes + censorCodes: + - ShadowedName + # optional, NonEmptyArray, only show specific codes + filterCodes: + - ShadowedName + # optional, whether to show statistics at the end + # of warning/error output and how much informaiton + statVerbosity: + # One of 3 values + # 1. Don't show it + "no-stats" + # 2. Show it and only sum the total warnings/errors + "compact-stats" + # 3. Show it and show total warnings/errors by code + "verbose-stats" + # optional, boolean, whether to show the source code + # corresponding to the error's location + showSource: true + # optional, boolean, counts compiler warnings as compiler errors + strict: false + # optional, Boolean String, persist compiler warnings + stash: true # optional bundle: @@ -379,10 +377,10 @@ workspace: output: "output" # optional, Boolean, fail the build if `spago.yml` has redundant/missing packages pedantic_packages: false - # optional, PsaOptions - # These options apply when a package does not specify the same value. - psaOptions: - # see the Package's `psaOptions` field + # All of the Package's `buildOptions` fields (e.g. `strict` as shown below) + # can also go here. Any specified here will be used + # if the selected package doesn't specify that option in its configuration + strict: false ``` ### FAQs diff --git a/spaghetto/bin/src/Main.purs b/spaghetto/bin/src/Main.purs index 30bd660c4..eb485ef4f 100644 --- a/spaghetto/bin/src/Main.purs +++ b/spaghetto/bin/src/Main.purs @@ -46,7 +46,6 @@ import Spago.Log (LogVerbosity(..)) import Spago.Paths as Paths import Spago.Purs (Purs) import Spago.Purs as Purs -import Type.Proxy (Proxy(..)) import Unsafe.Coerce (unsafeCoerce) type GlobalArgs = @@ -73,11 +72,7 @@ type InstallArgs = , output :: Maybe String , pedanticPackages :: Boolean , ensureRanges :: Boolean - , psaArgs :: PsaArgs - } - -type PsaArgs = - { strict :: Maybe Boolean + , strict :: Maybe Boolean , censorBuildWarnings :: Maybe Core.CensorBuildWarnings , showSource :: Maybe Core.ShowSourceCode , censorCodes :: Maybe (NonEmptySet String) @@ -94,7 +89,13 @@ type BuildArgs a = , pedanticPackages :: Boolean , ensureRanges :: Boolean , jsonErrors :: Boolean - , psaArgs :: PsaArgs + , strict :: Maybe Boolean + , censorBuildWarnings :: Maybe Core.CensorBuildWarnings + , showSource :: Maybe Core.ShowSourceCode + , censorCodes :: Maybe (NonEmptySet String) + , filterCodes :: Maybe (NonEmptySet String) + , statVerbosity :: Maybe Core.StatVerbosity + , stash :: Maybe Boolean | a } @@ -114,7 +115,13 @@ type RunArgs = , execArgs :: Maybe (Array String) , main :: Maybe String , ensureRanges :: Boolean - , psaArgs :: PsaArgs + , strict :: Maybe Boolean + , censorBuildWarnings :: Maybe Core.CensorBuildWarnings + , showSource :: Maybe Core.ShowSourceCode + , censorCodes :: Maybe (NonEmptySet String) + , filterCodes :: Maybe (NonEmptySet String) + , statVerbosity :: Maybe Core.StatVerbosity + , stash :: Maybe Boolean } type TestArgs = @@ -124,7 +131,13 @@ type TestArgs = , pursArgs :: List String , backendArgs :: List String , execArgs :: Maybe (Array String) - , psaArgs :: PsaArgs + , strict :: Maybe Boolean + , censorBuildWarnings :: Maybe Core.CensorBuildWarnings + , showSource :: Maybe Core.ShowSourceCode + , censorCodes :: Maybe (NonEmptySet String) + , filterCodes :: Maybe (NonEmptySet String) + , statVerbosity :: Maybe Core.StatVerbosity + , stash :: Maybe Boolean } type SourcesArgs = @@ -153,12 +166,24 @@ type BundleArgs = , pedanticPackages :: Boolean , type :: Maybe String , ensureRanges :: Boolean - , psaArgs :: PsaArgs + , strict :: Maybe Boolean + , censorBuildWarnings :: Maybe Core.CensorBuildWarnings + , showSource :: Maybe Core.ShowSourceCode + , censorCodes :: Maybe (NonEmptySet String) + , filterCodes :: Maybe (NonEmptySet String) + , statVerbosity :: Maybe Core.StatVerbosity + , stash :: Maybe Boolean } type PublishArgs = { selectedPackage :: Maybe String - , psaArgs :: PsaArgs + , strict :: Maybe Boolean + , censorBuildWarnings :: Maybe Core.CensorBuildWarnings + , showSource :: Maybe Core.ShowSourceCode + , censorCodes :: Maybe (NonEmptySet String) + , filterCodes :: Maybe (NonEmptySet String) + , statVerbosity :: Maybe Core.StatVerbosity + , stash :: Maybe Boolean } data SpagoCmd a = SpagoCmd GlobalArgs (Command a) @@ -295,20 +320,15 @@ installArgsParser = , output: Flags.output , pedanticPackages: Flags.pedanticPackages , ensureRanges: Flags.ensureRanges - , psaArgs: psaArgsParser + , strict: Flags.strict + , censorBuildWarnings: Flags.censorBuildWarnings + , showSource: Flags.showSource + , censorCodes: Flags.censorCodes + , filterCodes: Flags.filterCodes + , statVerbosity: Flags.statVerbosity + , stash: Flags.stash } -psaArgsParser :: ArgParser PsaArgs -psaArgsParser = ArgParser.fromRecord - { strict: Flags.strict - , censorBuildWarnings: Flags.censorBuildWarnings - , showSource: Flags.showSource - , censorCodes: Flags.censorCodes - , filterCodes: Flags.filterCodes - , statVerbosity: Flags.statVerbosity - , stash: Flags.stash - } - buildArgsParser :: ArgParser (BuildArgs ()) buildArgsParser = ArgParser.fromRecord { selectedPackage: Flags.selectedPackage @@ -318,7 +338,13 @@ buildArgsParser = ArgParser.fromRecord , pedanticPackages: Flags.pedanticPackages , ensureRanges: Flags.ensureRanges , jsonErrors: Flags.jsonErrors - , psaArgs: psaArgsParser + , strict: Flags.strict + , censorBuildWarnings: Flags.censorBuildWarnings + , showSource: Flags.showSource + , censorCodes: Flags.censorCodes + , filterCodes: Flags.filterCodes + , statVerbosity: Flags.statVerbosity + , stash: Flags.stash } replArgsParser :: ArgParser ReplArgs @@ -338,7 +364,13 @@ runArgsParser = ArgParser.fromRecord , pedanticPackages: Flags.pedanticPackages , main: Flags.moduleName , ensureRanges: Flags.ensureRanges - , psaArgs: psaArgsParser + , strict: Flags.strict + , censorBuildWarnings: Flags.censorBuildWarnings + , showSource: Flags.showSource + , censorCodes: Flags.censorCodes + , filterCodes: Flags.filterCodes + , statVerbosity: Flags.statVerbosity + , stash: Flags.stash } testArgsParser :: ArgParser TestArgs @@ -349,7 +381,13 @@ testArgsParser = ArgParser.fromRecord , execArgs: Flags.execArgs , output: Flags.output , pedanticPackages: Flags.pedanticPackages - , psaArgs: psaArgsParser + , strict: Flags.strict + , censorBuildWarnings: Flags.censorBuildWarnings + , showSource: Flags.showSource + , censorCodes: Flags.censorCodes + , filterCodes: Flags.filterCodes + , statVerbosity: Flags.statVerbosity + , stash: Flags.stash } bundleArgsParser :: ArgParser BundleArgs @@ -366,14 +404,26 @@ bundleArgsParser = , output: Flags.output , pedanticPackages: Flags.pedanticPackages , ensureRanges: Flags.ensureRanges - , psaArgs: psaArgsParser + , strict: Flags.strict + , censorBuildWarnings: Flags.censorBuildWarnings + , showSource: Flags.showSource + , censorCodes: Flags.censorCodes + , filterCodes: Flags.filterCodes + , statVerbosity: Flags.statVerbosity + , stash: Flags.stash } publishArgsParser :: ArgParser PublishArgs publishArgsParser = ArgParser.fromRecord { selectedPackage: Flags.selectedPackage - , psaArgs: psaArgsParser + , strict: Flags.strict + , censorBuildWarnings: Flags.censorBuildWarnings + , showSource: Flags.showSource + , censorCodes: Flags.censorCodes + , filterCodes: Flags.filterCodes + , statVerbosity: Flags.statVerbosity + , stash: Flags.stash } registrySearchArgsParser :: ArgParser RegistrySearchArgs @@ -457,23 +507,30 @@ main = buildEnv <- runSpago env (mkBuildEnv args dependencies) let options = { depsOnly: false, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors } runSpago buildEnv (Build.run options) - Publish { selectedPackage, psaArgs } -> do + Publish { selectedPackage } -> do { env, fetchOpts } <- mkFetchEnv { packages: mempty, selectedPackage, ensureRanges: false } -- TODO: --no-fetch flag dependencies <- runSpago env (Fetch.run fetchOpts) let buildArgs = { selectedPackage - , psaArgs -- , pursArgs: mempty , backendArgs: mempty , output: mempty , pedanticPackages: false , ensureRanges: false , jsonErrors: false + -- Note: in a future commit, we will drop the PSA args in the `PublishArgs` record + , censorBuildWarnings: Nothing :: Maybe Core.CensorBuildWarnings + , censorCodes: Nothing :: Maybe (NonEmptySet String) + , filterCodes: Nothing :: Maybe (NonEmptySet String) + , statVerbosity: Nothing :: Maybe Core.StatVerbosity + , showSource: Nothing :: Maybe Core.ShowSourceCode + , strict: Nothing :: Maybe Boolean + , stash: Nothing :: Maybe Boolean } - { purs, psaConfig } <- runSpago env (mkBuildEnv buildArgs dependencies) - publishEnv <- runSpago env (mkPublishEnv dependencies purs psaConfig) + { purs } <- runSpago env (mkBuildEnv buildArgs dependencies) + publishEnv <- runSpago env (mkPublishEnv dependencies purs) void $ runSpago publishEnv (Publish.publish {}) Repl args -> do -- TODO implement @@ -672,7 +729,13 @@ mkBuildEnv . { backendArgs :: List String , output :: Maybe String , pedanticPackages :: Boolean - , psaArgs :: PsaArgs + , censorBuildWarnings :: Maybe Core.CensorBuildWarnings + , censorCodes :: Maybe (NonEmptySet String) + , filterCodes :: Maybe (NonEmptySet String) + , statVerbosity :: Maybe Core.StatVerbosity + , showSource :: Maybe Core.ShowSourceCode + , strict :: Maybe Boolean + , stash :: Maybe Boolean | r } -> Map PackageName Package @@ -695,34 +758,26 @@ mkBuildEnv buildArgs dependencies = do workspace.backend } - psaConfig :: Core.PsaConfig - psaConfig = - { strict: getField $ Record.get (Proxy :: Proxy "strict") - , censorBuildWarnings: getField $ Record.get (Proxy :: Proxy "censorBuildWarnings") - , showSource: getField $ Record.get (Proxy :: Proxy "showSource") - , censorCodes: getField $ Record.get (Proxy :: Proxy "censorCodes") - , filterCodes: getField $ Record.get (Proxy :: Proxy "filterCodes") - , statVerbosity: getField $ Record.get (Proxy :: Proxy "statVerbosity") - , stash: getField $ Record.get (Proxy :: Proxy "stash") - } - where - getField :: forall a. (Core.PsaConfig -> Maybe a) -> Maybe a - getField getLabel = oneOf - [ getLabel buildArgs.psaArgs - , packagePsaConfig >>= getLabel - , workspacePsaConfig >>= getLabel - ] - - packagePsaConfig :: Maybe Core.PsaConfig - packagePsaConfig = workspace.selected >>= \p -> p.package.build >>= _.psaOptions + packageBuildConfig = workspace.selected >>= \p -> p.package.build + workspaceBuildConfig = workspace.buildOptions - workspacePsaConfig :: Maybe Core.PsaConfig - workspacePsaConfig = workspace.buildOptions.psaOptions - - pure { logOptions, purs, git, dependencies, workspace: newWorkspace, psaConfig } + pure + { logOptions + , purs + , git + , dependencies + , workspace: newWorkspace + , strict: oneOf [ buildArgs.strict, packageBuildConfig >>= _.strict, workspaceBuildConfig.strict ] + , censorBuildWarnings: oneOf [ buildArgs.censorBuildWarnings, packageBuildConfig >>= _.censorBuildWarnings, workspaceBuildConfig.censorBuildWarnings ] + , showSource: oneOf [ buildArgs.showSource, packageBuildConfig >>= _.showSource, workspaceBuildConfig.showSource ] + , censorCodes: oneOf [ buildArgs.censorCodes, packageBuildConfig >>= _.censorCodes, workspaceBuildConfig.censorCodes ] + , filterCodes: oneOf [ buildArgs.filterCodes, packageBuildConfig >>= _.filterCodes, workspaceBuildConfig.filterCodes ] + , statVerbosity: oneOf [ buildArgs.statVerbosity, packageBuildConfig >>= _.statVerbosity, workspaceBuildConfig.statVerbosity ] + , stash: oneOf [ buildArgs.stash, packageBuildConfig >>= _.stash, workspaceBuildConfig.stash ] + } -mkPublishEnv :: forall a. Map PackageName Package -> Purs -> Config.PsaConfig -> Spago (Fetch.FetchEnv a) (Publish.PublishEnv a) -mkPublishEnv dependencies purs psaConfig = do +mkPublishEnv :: forall a. Map PackageName Package -> Purs -> Spago (Fetch.FetchEnv a) (Publish.PublishEnv a) +mkPublishEnv dependencies purs = do env <- ask selected <- case env.workspace.selected of Just s -> pure s @@ -739,7 +794,7 @@ mkPublishEnv dependencies purs psaConfig = do [ toDoc "No package was selected for publishing. Please select (with -p) one of the following packages:" , indent (toDoc $ map _.package.name workspacePackages) ] - pure (Record.union { purs, selected, dependencies, psaConfig } env) + pure (Record.union { purs, selected, dependencies } env) mkFetchEnv :: forall a. FetchArgs -> Spago (LogEnv a) { env :: Fetch.FetchEnv (), fetchOpts :: Fetch.FetchOpts } mkFetchEnv args = do diff --git a/spaghetto/core/src/Config.purs b/spaghetto/core/src/Config.purs index d5fab0b86..47a7a3071 100644 --- a/spaghetto/core/src/Config.purs +++ b/spaghetto/core/src/Config.purs @@ -2,7 +2,6 @@ module Spago.Core.Config ( BackendConfig , BuildOptionsInput , BuildConfig - , PsaConfig , CensorBuildWarnings(..) , ShowSourceCode(..) , StatVerbosity(..) @@ -80,15 +79,6 @@ type PackageConfig = } type BuildConfig = - { psaOptions :: Maybe PsaConfig - } - -buildConfigCodec :: JsonCodec BuildConfig -buildConfigCodec = CAR.object "BuildConfig" - { psaOptions: CAR.optional psaConfigCodec - } - -type PsaConfig = { censorBuildWarnings :: Maybe CensorBuildWarnings , censorCodes :: Maybe (NonEmptySet.NonEmptySet String) , filterCodes :: Maybe (NonEmptySet.NonEmptySet String) @@ -98,8 +88,8 @@ type PsaConfig = , stash :: Maybe Boolean } -psaConfigCodec :: JsonCodec PsaConfig -psaConfigCodec = CAR.object "PsaConfig" +buildConfigCodec :: JsonCodec BuildConfig +buildConfigCodec = CAR.object "BuildConfig" { censorBuildWarnings: CAR.optional censorBuildWarningsCodec , censorCodes: CAR.optional $ CA.Common.nonEmptySet CA.string , filterCodes: CAR.optional $ CA.Common.nonEmptySet CA.string @@ -225,7 +215,13 @@ type TestConfig = { main :: String , execArgs :: Maybe (Array String) , dependencies :: Dependencies - , psaOptions :: Maybe PsaConfig + , censorBuildWarnings :: Maybe CensorBuildWarnings + , censorCodes :: Maybe (NonEmptySet.NonEmptySet String) + , filterCodes :: Maybe (NonEmptySet.NonEmptySet String) + , statVerbosity :: Maybe StatVerbosity + , showSource :: Maybe ShowSourceCode + , strict :: Maybe Boolean + , stash :: Maybe Boolean } testConfigCodec :: JsonCodec TestConfig @@ -233,7 +229,13 @@ testConfigCodec = CAR.object "TestConfig" { main: CA.string , execArgs: CAR.optional (CA.array CA.string) , dependencies: dependenciesCodec - , psaOptions: CAR.optional psaConfigCodec + , censorBuildWarnings: CAR.optional censorBuildWarningsCodec + , censorCodes: CAR.optional $ CA.Common.nonEmptySet CA.string + , filterCodes: CAR.optional $ CA.Common.nonEmptySet CA.string + , statVerbosity: CAR.optional statVerbosityCodec + , showSource: CAR.optional showSourceCodec + , strict: CAR.optional CA.boolean + , stash: CAR.optional CA.boolean } type BackendConfig = @@ -383,14 +385,26 @@ workspaceConfigCodec = CAR.object "WorkspaceConfig" type BuildOptionsInput = { output :: Maybe FilePath , pedantic_packages :: Maybe Boolean - , psaOptions :: Maybe PsaConfig + , censorBuildWarnings :: Maybe CensorBuildWarnings + , censorCodes :: Maybe (NonEmptySet.NonEmptySet String) + , filterCodes :: Maybe (NonEmptySet.NonEmptySet String) + , statVerbosity :: Maybe StatVerbosity + , showSource :: Maybe ShowSourceCode + , strict :: Maybe Boolean + , stash :: Maybe Boolean } buildOptionsCodec :: JsonCodec BuildOptionsInput buildOptionsCodec = CAR.object "CompileOptionsInput" { output: CAR.optional CA.string , pedantic_packages: CAR.optional CA.boolean - , psaOptions: CAR.optional psaConfigCodec + , censorBuildWarnings: CAR.optional censorBuildWarningsCodec + , censorCodes: CAR.optional $ CA.Common.nonEmptySet CA.string + , filterCodes: CAR.optional $ CA.Common.nonEmptySet CA.string + , statVerbosity: CAR.optional statVerbosityCodec + , showSource: CAR.optional showSourceCodec + , strict: CAR.optional CA.boolean + , stash: CAR.optional CA.boolean } data SetAddress diff --git a/spaghetto/src/Spago/Command/Build.purs b/spaghetto/src/Spago/Command/Build.purs index d2afab994..c42f2aaa1 100644 --- a/spaghetto/src/Spago/Command/Build.purs +++ b/spaghetto/src/Spago/Command/Build.purs @@ -9,13 +9,15 @@ import Control.Alternative as Alternative import Data.Array as Array import Data.Map as Map import Data.Set as Set +import Data.Set.NonEmpty (NonEmptySet) import Data.Set.NonEmpty as NonEmptySet import Data.Tuple as Tuple import Registry.PackageName as PackageName import Spago.BuildInfo as BuildInfo import Spago.Cmd as Cmd -import Spago.Config (Package(..), PsaConfig, WithTestGlobs(..), Workspace, WorkspacePackage) +import Spago.Config (Package(..), WithTestGlobs(..), Workspace, WorkspacePackage) import Spago.Config as Config +import Spago.Config as Core import Spago.Git (Git) import Spago.Paths as Paths import Spago.Psa as Psa @@ -28,7 +30,13 @@ type BuildEnv a = , dependencies :: Map PackageName Package , logOptions :: LogOptions , workspace :: Workspace - , psaConfig :: PsaConfig + , censorBuildWarnings :: Maybe Core.CensorBuildWarnings + , censorCodes :: Maybe (NonEmptySet String) + , filterCodes :: Maybe (NonEmptySet String) + , statVerbosity :: Maybe Core.StatVerbosity + , showSource :: Maybe Core.ShowSourceCode + , strict :: Maybe Boolean + , stash :: Maybe Boolean | a } @@ -41,7 +49,17 @@ type BuildOptions = run :: forall a. BuildOptions -> Spago (BuildEnv a) Unit run opts = do logInfo "Building..." - { dependencies, workspace, logOptions, psaConfig } <- ask + { dependencies + , workspace + , logOptions + , censorBuildWarnings + , censorCodes + , filterCodes + , statVerbosity + , showSource + , strict + , stash + } <- ask let isWorkspacePackage = case _ of Tuple _ (WorkspacePackage _) -> true @@ -92,16 +110,16 @@ run opts = do , jsonErrors: opts.jsonErrors } psaOptions = - { strict: fromMaybe Psa.defaultParseOptions.strict psaConfig.strict - , censorBuildWarnings: fromMaybe Psa.defaultParseOptions.censorBuildWarnings psaConfig.censorBuildWarnings - , showSource: fromMaybe Psa.defaultParseOptions.showSource psaConfig.showSource - , censorCodes: maybe Psa.defaultParseOptions.censorCodes NonEmptySet.toSet psaConfig.censorCodes - , filterCodes: maybe Psa.defaultParseOptions.filterCodes NonEmptySet.toSet psaConfig.filterCodes - , statVerbosity: fromMaybe Psa.defaultParseOptions.statVerbosity psaConfig.statVerbosity + { strict: fromMaybe Psa.defaultParseOptions.strict strict + , censorBuildWarnings: fromMaybe Psa.defaultParseOptions.censorBuildWarnings censorBuildWarnings + , showSource: fromMaybe Psa.defaultParseOptions.showSource showSource + , censorCodes: maybe Psa.defaultParseOptions.censorCodes NonEmptySet.toSet censorCodes + , filterCodes: maybe Psa.defaultParseOptions.filterCodes NonEmptySet.toSet filterCodes + , statVerbosity: fromMaybe Psa.defaultParseOptions.statVerbosity statVerbosity , stashFile: do Alternative.guard (not opts.depsOnly) - stash <- psaConfig.stash - Alternative.guard stash + shouldStashWarnings <- stash + Alternative.guard shouldStashWarnings case workspace.selected of Just p -> Just $ Paths.mkLocalCachesStashFile $ PackageName.print p.package.name Nothing -> Just Paths.localCachesStashEntireWorkspace diff --git a/spaghetto/src/Spago/Command/Init.purs b/spaghetto/src/Spago/Command/Init.purs index 67e53b8fb..e87bac809 100644 --- a/spaghetto/src/Spago/Command/Init.purs +++ b/spaghetto/src/Spago/Command/Init.purs @@ -88,7 +88,13 @@ defaultConfig name set = { dependencies: Dependencies Map.empty , execArgs: Nothing , main: "Test.Main" - , psaOptions: Nothing + , censorBuildWarnings: Nothing + , censorCodes: Nothing + , filterCodes: Nothing + , statVerbosity: Nothing + , showSource: Nothing + , strict: Nothing + , stash: Nothing } , publish: Nothing , bundle: Nothing diff --git a/spaghetto/src/Spago/Command/Publish.purs b/spaghetto/src/Spago/Command/Publish.purs index 239c4b082..51f5f300f 100644 --- a/spaghetto/src/Spago/Command/Publish.purs +++ b/spaghetto/src/Spago/Command/Publish.purs @@ -7,6 +7,7 @@ import Data.Codec.Argonaut as CA import Data.List as List import Data.Map as Map import Data.Set as Set +import Data.Set.NonEmpty (NonEmptySet) import Data.Tuple as Tuple import Effect.Ref as Ref import Node.Path as Path @@ -19,8 +20,9 @@ import Registry.Solver as Registry.Solver import Registry.Version as Version import Spago.BuildInfo as BuildInfo import Spago.Command.Build as Build -import Spago.Config (Package(..), WithTestGlobs(..), Workspace, WorkspacePackage, PsaConfig) +import Spago.Config (Package(..), WithTestGlobs(..), Workspace, WorkspacePackage) import Spago.Config as Config +import Spago.Config as Core import Spago.Git (Git) import Spago.Git as Git import Spago.Json as Json @@ -46,7 +48,6 @@ type PublishEnv a = , purs :: Purs , selected :: WorkspacePackage , dependencies :: Map PackageName Package - , psaConfig :: PsaConfig | a } @@ -75,7 +76,6 @@ publish _args = do env@ { selected: selected' - , workspace , purs , dependencies , logOptions @@ -90,8 +90,30 @@ publish _args = do -- As first thing we run a build to make sure the package compiles at all runSpago - (env { workspace = workspace { selected = Just selected } }) - (Build.run { depsOnly: false, pursArgs: [], jsonErrors: false }) + -- We explicitly list the env fields because `Record.merge` didn't compile. + { getManifestFromIndex: env.getManifestFromIndex + , getMetadata: env.getMetadata + , getCachedIndex: env.getCachedIndex + , workspace: env.workspace { selected = Just selected } + , logOptions: env.logOptions + , git: env.git + , purs: env.purs + , selected: env.selected + , dependencies: env.dependencies + , censorBuildWarnings: (Nothing :: Maybe Core.CensorBuildWarnings) + , censorCodes: (Nothing :: Maybe (NonEmptySet String)) + , filterCodes: (Nothing :: Maybe (NonEmptySet String)) + , statVerbosity: (Nothing :: Maybe Core.StatVerbosity) + , showSource: (Nothing :: Maybe Core.ShowSourceCode) + , strict: (Nothing :: Maybe Boolean) + , stash: (Nothing :: Maybe Boolean) + } + ( Build.run + { depsOnly: false + , pursArgs: [] + , jsonErrors: false + } + ) -- We then need to check that the dependency graph is accurate. If not, queue the errors let globs = getGlobs selected dependencies @@ -232,12 +254,30 @@ publish _args = do -- from the solver (this is because the build might terminate the process, and we shall output the errors first) let buildPlanDependencies = map Config.RegistryVersion resolutions runSpago - ( env - { workspace = workspace { selected = Just selected } - , dependencies = buildPlanDependencies + -- We explicitly list the env fields because `Record.merge` didn't compile. + { getManifestFromIndex: env.getManifestFromIndex + , getMetadata: env.getMetadata + , getCachedIndex: env.getCachedIndex + , workspace: env.workspace { selected = Just selected } + , logOptions: env.logOptions + , git: env.git + , purs: env.purs + , selected: env.selected + , dependencies: buildPlanDependencies + , censorBuildWarnings: (Nothing :: Maybe Core.CensorBuildWarnings) + , censorCodes: (Nothing :: Maybe (NonEmptySet String)) + , filterCodes: (Nothing :: Maybe (NonEmptySet String)) + , statVerbosity: (Nothing :: Maybe Core.StatVerbosity) + , showSource: (Nothing :: Maybe Core.ShowSourceCode) + , strict: (Nothing :: Maybe Boolean) + , stash: (Nothing :: Maybe Boolean) + } + ( Build.run + { depsOnly: false + , pursArgs: [] + , jsonErrors: false } ) - (Build.run { depsOnly: false, pursArgs: [], jsonErrors: false }) logDebug $ unsafeStringify publishingData logSuccess "Ready for publishing. Calling the registry.." diff --git a/spaghetto/src/Spago/Config.purs b/spaghetto/src/Spago/Config.purs index 0d7f1c46c..164da770e 100644 --- a/spaghetto/src/Spago/Config.purs +++ b/spaghetto/src/Spago/Config.purs @@ -27,6 +27,7 @@ import Data.HTTP.Method as Method import Data.Map as Map import Data.Profunctor as Profunctor import Data.Set as Set +import Data.Set.NonEmpty (NonEmptySet) import Data.String (Pattern(..)) import Data.String as String import Dodo as Log @@ -59,7 +60,13 @@ type Workspace = type BuildOptions = { output :: Maybe FilePath , pedanticPackages :: Boolean - , psaOptions :: Maybe Core.PsaConfig + , censorBuildWarnings :: Maybe Core.CensorBuildWarnings + , censorCodes :: Maybe (NonEmptySet String) + , filterCodes :: Maybe (NonEmptySet String) + , statVerbosity :: Maybe Core.StatVerbosity + , showSource :: Maybe Core.ShowSourceCode + , strict :: Maybe Boolean + , stash :: Maybe Boolean } fromExtraPackage :: Core.ExtraPackage -> Package @@ -299,7 +306,13 @@ readWorkspace maybeSelectedPackage = do (buildOptions :: BuildOptions) = { output: _.output =<< workspace.build_opts , pedanticPackages: fromMaybe false (_.pedantic_packages =<< workspace.build_opts) - , psaOptions: _.psaOptions =<< workspace.build_opts + , censorBuildWarnings: _.censorBuildWarnings =<< workspace.build_opts + , censorCodes: _.censorCodes =<< workspace.build_opts + , filterCodes: _.filterCodes =<< workspace.build_opts + , statVerbosity: _.statVerbosity =<< workspace.build_opts + , showSource: _.showSource =<< workspace.build_opts + , strict: _.strict =<< workspace.build_opts + , stash: _.stash =<< workspace.build_opts } pure From 0718725e6670f0801fd74938a0f18a67f1e10193 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 19 Apr 2023 12:27:35 -0500 Subject: [PATCH 72/78] Drop psa args from Install/Publish CLI flags --- spaghetto/bin/src/Main.purs | 42 +++++++++++-------------------------- 1 file changed, 12 insertions(+), 30 deletions(-) diff --git a/spaghetto/bin/src/Main.purs b/spaghetto/bin/src/Main.purs index eb485ef4f..442e94dd9 100644 --- a/spaghetto/bin/src/Main.purs +++ b/spaghetto/bin/src/Main.purs @@ -72,13 +72,6 @@ type InstallArgs = , output :: Maybe String , pedanticPackages :: Boolean , ensureRanges :: Boolean - , strict :: Maybe Boolean - , censorBuildWarnings :: Maybe Core.CensorBuildWarnings - , showSource :: Maybe Core.ShowSourceCode - , censorCodes :: Maybe (NonEmptySet String) - , filterCodes :: Maybe (NonEmptySet String) - , statVerbosity :: Maybe Core.StatVerbosity - , stash :: Maybe Boolean } type BuildArgs a = @@ -177,13 +170,6 @@ type BundleArgs = type PublishArgs = { selectedPackage :: Maybe String - , strict :: Maybe Boolean - , censorBuildWarnings :: Maybe Core.CensorBuildWarnings - , showSource :: Maybe Core.ShowSourceCode - , censorCodes :: Maybe (NonEmptySet String) - , filterCodes :: Maybe (NonEmptySet String) - , statVerbosity :: Maybe Core.StatVerbosity - , stash :: Maybe Boolean } data SpagoCmd a = SpagoCmd GlobalArgs (Command a) @@ -320,13 +306,6 @@ installArgsParser = , output: Flags.output , pedanticPackages: Flags.pedanticPackages , ensureRanges: Flags.ensureRanges - , strict: Flags.strict - , censorBuildWarnings: Flags.censorBuildWarnings - , showSource: Flags.showSource - , censorCodes: Flags.censorCodes - , filterCodes: Flags.filterCodes - , statVerbosity: Flags.statVerbosity - , stash: Flags.stash } buildArgsParser :: ArgParser (BuildArgs ()) @@ -417,13 +396,6 @@ publishArgsParser :: ArgParser PublishArgs publishArgsParser = ArgParser.fromRecord { selectedPackage: Flags.selectedPackage - , strict: Flags.strict - , censorBuildWarnings: Flags.censorBuildWarnings - , showSource: Flags.showSource - , censorCodes: Flags.censorCodes - , filterCodes: Flags.filterCodes - , statVerbosity: Flags.statVerbosity - , stash: Flags.stash } registrySearchArgsParser :: ArgParser RegistrySearchArgs @@ -497,7 +469,18 @@ main = { env, fetchOpts } <- mkFetchEnv { packages, selectedPackage, ensureRanges } -- TODO: --no-fetch flag dependencies <- runSpago env (Fetch.run fetchOpts) - env' <- runSpago env (mkBuildEnv args dependencies) + let + buildArgs = Record.merge + args + { censorBuildWarnings: Nothing :: Maybe Core.CensorBuildWarnings + , censorCodes: Nothing :: Maybe (NonEmptySet String) + , filterCodes: Nothing :: Maybe (NonEmptySet String) + , statVerbosity: Nothing :: Maybe Core.StatVerbosity + , showSource: Nothing :: Maybe Core.ShowSourceCode + , strict: Nothing :: Maybe Boolean + , stash: Nothing :: Maybe Boolean + } + env' <- runSpago env (mkBuildEnv buildArgs dependencies) let options = { depsOnly: true, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors: false } runSpago env' (Build.run options) Build args@{ selectedPackage, ensureRanges, jsonErrors } -> do @@ -520,7 +503,6 @@ main = , pedanticPackages: false , ensureRanges: false , jsonErrors: false - -- Note: in a future commit, we will drop the PSA args in the `PublishArgs` record , censorBuildWarnings: Nothing :: Maybe Core.CensorBuildWarnings , censorCodes: Nothing :: Maybe (NonEmptySet String) , filterCodes: Nothing :: Maybe (NonEmptySet String) From 443bb857364f25c0d8f9581073817d69c31e71aa Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 19 Apr 2023 12:28:28 -0500 Subject: [PATCH 73/78] CLI flags: `---` -> `--` --- spaghetto/bin/src/Flags.purs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/spaghetto/bin/src/Flags.purs b/spaghetto/bin/src/Flags.purs index 29a816d0e..3f3a36127 100644 --- a/spaghetto/bin/src/Flags.purs +++ b/spaghetto/bin/src/Flags.purs @@ -24,7 +24,7 @@ strict = censorBuildWarnings ∷ ArgParser (Maybe Core.CensorBuildWarnings) censorBuildWarnings = - ArgParser.argument [ "---censor-build-warnings" ] + ArgParser.argument [ "--censor-build-warnings" ] "Censor compiler warnings based on file's location: 'dependency', 'project', or 'all'" # ArgParser.unformat "ARG" ( case _ of @@ -38,33 +38,33 @@ censorBuildWarnings = showSource ∷ ArgParser (Maybe ShowSourceCode) showSource = NoSourceCode - <$ ArgParser.flag [ "---no-source" ] + <$ ArgParser.flag [ "--no-source" ] "Disable original source code printing" # ArgParser.optional censorCodes :: ArgParser (Maybe (NonEmptySet String)) censorCodes = - ArgParser.argument [ "---censor-code" ] + ArgParser.argument [ "--censor-code" ] "Censor a specific error code (e.g. `ShadowedName`)" # ArgParser.many <#> NonEmptySet.fromFoldable filterCodes :: ArgParser (Maybe (NonEmptySet String)) filterCodes = - ArgParser.argument [ "---filter-code" ] + ArgParser.argument [ "--filter-code" ] "Only show a specific error code (e.g. `TypesDoNotUnify`)" # ArgParser.many <#> NonEmptySet.fromFoldable statVerbosity :: ArgParser (Maybe Core.StatVerbosity) statVerbosity = ArgParser.optional $ ArgParser.choose "StatVerbosity" - [ Core.VerboseStats <$ ArgParser.flag [ "---verbose-stats" ] "Show counts for each warning type" - , Core.NoStats <$ ArgParser.flag [ "---censor-stats" ] "Censor warning/error summary" + [ Core.VerboseStats <$ ArgParser.flag [ "--verbose-stats" ] "Show counts for each warning type" + , Core.NoStats <$ ArgParser.flag [ "--censor-stats" ] "Censor warning/error summary" ] stash ∷ ArgParser (Maybe Boolean) stash = - ArgParser.flag [ "---stash" ] "Enable persistent warnings using default stash file location" + ArgParser.flag [ "--stash" ] "Enable persistent warnings using default stash file location" # ArgParser.boolean # ArgParser.optional From abcf5fdfbe1be92ea795ea8aee63c13162d10545 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 19 Apr 2023 12:36:10 -0500 Subject: [PATCH 74/78] Rename 'stash' to 'persist-warnings' --- spaghetto/bin/src/Flags.purs | 6 +++--- spaghetto/bin/src/Main.purs | 24 ++++++++++++------------ spaghetto/core/src/Config.purs | 12 ++++++------ spaghetto/src/Spago/Command/Build.purs | 10 +++++----- spaghetto/src/Spago/Command/Init.purs | 2 +- spaghetto/src/Spago/Command/Publish.purs | 4 ++-- spaghetto/src/Spago/Config.purs | 4 ++-- spaghetto/src/Spago/Paths.purs | 12 ++++++------ 8 files changed, 37 insertions(+), 37 deletions(-) diff --git a/spaghetto/bin/src/Flags.purs b/spaghetto/bin/src/Flags.purs index 3f3a36127..57e54c118 100644 --- a/spaghetto/bin/src/Flags.purs +++ b/spaghetto/bin/src/Flags.purs @@ -62,9 +62,9 @@ statVerbosity = ArgParser.optional $ ArgParser.choose "StatVerbosity" , Core.NoStats <$ ArgParser.flag [ "--censor-stats" ] "Censor warning/error summary" ] -stash ∷ ArgParser (Maybe Boolean) -stash = - ArgParser.flag [ "--stash" ] "Enable persistent warnings using default stash file location" +persistWarnings ∷ ArgParser (Maybe Boolean) +persistWarnings = + ArgParser.flag [ "--persist-warnings" ] "Enable persistent warnings using default persist-warnings file location" # ArgParser.boolean # ArgParser.optional diff --git a/spaghetto/bin/src/Main.purs b/spaghetto/bin/src/Main.purs index 442e94dd9..061fc8421 100644 --- a/spaghetto/bin/src/Main.purs +++ b/spaghetto/bin/src/Main.purs @@ -88,7 +88,7 @@ type BuildArgs a = , censorCodes :: Maybe (NonEmptySet String) , filterCodes :: Maybe (NonEmptySet String) , statVerbosity :: Maybe Core.StatVerbosity - , stash :: Maybe Boolean + , persistWarnings :: Maybe Boolean | a } @@ -114,7 +114,7 @@ type RunArgs = , censorCodes :: Maybe (NonEmptySet String) , filterCodes :: Maybe (NonEmptySet String) , statVerbosity :: Maybe Core.StatVerbosity - , stash :: Maybe Boolean + , persistWarnings :: Maybe Boolean } type TestArgs = @@ -130,7 +130,7 @@ type TestArgs = , censorCodes :: Maybe (NonEmptySet String) , filterCodes :: Maybe (NonEmptySet String) , statVerbosity :: Maybe Core.StatVerbosity - , stash :: Maybe Boolean + , persistWarnings :: Maybe Boolean } type SourcesArgs = @@ -165,7 +165,7 @@ type BundleArgs = , censorCodes :: Maybe (NonEmptySet String) , filterCodes :: Maybe (NonEmptySet String) , statVerbosity :: Maybe Core.StatVerbosity - , stash :: Maybe Boolean + , persistWarnings :: Maybe Boolean } type PublishArgs = @@ -323,7 +323,7 @@ buildArgsParser = ArgParser.fromRecord , censorCodes: Flags.censorCodes , filterCodes: Flags.filterCodes , statVerbosity: Flags.statVerbosity - , stash: Flags.stash + , persistWarnings: Flags.persistWarnings } replArgsParser :: ArgParser ReplArgs @@ -349,7 +349,7 @@ runArgsParser = ArgParser.fromRecord , censorCodes: Flags.censorCodes , filterCodes: Flags.filterCodes , statVerbosity: Flags.statVerbosity - , stash: Flags.stash + , persistWarnings: Flags.persistWarnings } testArgsParser :: ArgParser TestArgs @@ -366,7 +366,7 @@ testArgsParser = ArgParser.fromRecord , censorCodes: Flags.censorCodes , filterCodes: Flags.filterCodes , statVerbosity: Flags.statVerbosity - , stash: Flags.stash + , persistWarnings: Flags.persistWarnings } bundleArgsParser :: ArgParser BundleArgs @@ -389,7 +389,7 @@ bundleArgsParser = , censorCodes: Flags.censorCodes , filterCodes: Flags.filterCodes , statVerbosity: Flags.statVerbosity - , stash: Flags.stash + , persistWarnings: Flags.persistWarnings } publishArgsParser :: ArgParser PublishArgs @@ -478,7 +478,7 @@ main = , statVerbosity: Nothing :: Maybe Core.StatVerbosity , showSource: Nothing :: Maybe Core.ShowSourceCode , strict: Nothing :: Maybe Boolean - , stash: Nothing :: Maybe Boolean + , persistWarnings: Nothing :: Maybe Boolean } env' <- runSpago env (mkBuildEnv buildArgs dependencies) let options = { depsOnly: true, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors: false } @@ -509,7 +509,7 @@ main = , statVerbosity: Nothing :: Maybe Core.StatVerbosity , showSource: Nothing :: Maybe Core.ShowSourceCode , strict: Nothing :: Maybe Boolean - , stash: Nothing :: Maybe Boolean + , persistWarnings: Nothing :: Maybe Boolean } { purs } <- runSpago env (mkBuildEnv buildArgs dependencies) publishEnv <- runSpago env (mkPublishEnv dependencies purs) @@ -717,7 +717,7 @@ mkBuildEnv , statVerbosity :: Maybe Core.StatVerbosity , showSource :: Maybe Core.ShowSourceCode , strict :: Maybe Boolean - , stash :: Maybe Boolean + , persistWarnings :: Maybe Boolean | r } -> Map PackageName Package @@ -755,7 +755,7 @@ mkBuildEnv buildArgs dependencies = do , censorCodes: oneOf [ buildArgs.censorCodes, packageBuildConfig >>= _.censorCodes, workspaceBuildConfig.censorCodes ] , filterCodes: oneOf [ buildArgs.filterCodes, packageBuildConfig >>= _.filterCodes, workspaceBuildConfig.filterCodes ] , statVerbosity: oneOf [ buildArgs.statVerbosity, packageBuildConfig >>= _.statVerbosity, workspaceBuildConfig.statVerbosity ] - , stash: oneOf [ buildArgs.stash, packageBuildConfig >>= _.stash, workspaceBuildConfig.stash ] + , persistWarnings: oneOf [ buildArgs.persistWarnings, packageBuildConfig >>= _.persistWarnings, workspaceBuildConfig.persistWarnings ] } mkPublishEnv :: forall a. Map PackageName Package -> Purs -> Spago (Fetch.FetchEnv a) (Publish.PublishEnv a) diff --git a/spaghetto/core/src/Config.purs b/spaghetto/core/src/Config.purs index 47a7a3071..d6dfe9e0e 100644 --- a/spaghetto/core/src/Config.purs +++ b/spaghetto/core/src/Config.purs @@ -85,7 +85,7 @@ type BuildConfig = , statVerbosity :: Maybe StatVerbosity , showSource :: Maybe ShowSourceCode , strict :: Maybe Boolean - , stash :: Maybe Boolean + , persistWarnings :: Maybe Boolean } buildConfigCodec :: JsonCodec BuildConfig @@ -96,7 +96,7 @@ buildConfigCodec = CAR.object "BuildConfig" , statVerbosity: CAR.optional statVerbosityCodec , showSource: CAR.optional showSourceCodec , strict: CAR.optional CA.boolean - , stash: CAR.optional CA.boolean + , persistWarnings: CAR.optional CA.boolean } data CensorBuildWarnings @@ -221,7 +221,7 @@ type TestConfig = , statVerbosity :: Maybe StatVerbosity , showSource :: Maybe ShowSourceCode , strict :: Maybe Boolean - , stash :: Maybe Boolean + , persistWarnings :: Maybe Boolean } testConfigCodec :: JsonCodec TestConfig @@ -235,7 +235,7 @@ testConfigCodec = CAR.object "TestConfig" , statVerbosity: CAR.optional statVerbosityCodec , showSource: CAR.optional showSourceCodec , strict: CAR.optional CA.boolean - , stash: CAR.optional CA.boolean + , persistWarnings: CAR.optional CA.boolean } type BackendConfig = @@ -391,7 +391,7 @@ type BuildOptionsInput = , statVerbosity :: Maybe StatVerbosity , showSource :: Maybe ShowSourceCode , strict :: Maybe Boolean - , stash :: Maybe Boolean + , persistWarnings :: Maybe Boolean } buildOptionsCodec :: JsonCodec BuildOptionsInput @@ -404,7 +404,7 @@ buildOptionsCodec = CAR.object "CompileOptionsInput" , statVerbosity: CAR.optional statVerbosityCodec , showSource: CAR.optional showSourceCodec , strict: CAR.optional CA.boolean - , stash: CAR.optional CA.boolean + , persistWarnings: CAR.optional CA.boolean } data SetAddress diff --git a/spaghetto/src/Spago/Command/Build.purs b/spaghetto/src/Spago/Command/Build.purs index c42f2aaa1..3fbe0374e 100644 --- a/spaghetto/src/Spago/Command/Build.purs +++ b/spaghetto/src/Spago/Command/Build.purs @@ -36,7 +36,7 @@ type BuildEnv a = , statVerbosity :: Maybe Core.StatVerbosity , showSource :: Maybe Core.ShowSourceCode , strict :: Maybe Boolean - , stash :: Maybe Boolean + , persistWarnings :: Maybe Boolean | a } @@ -58,7 +58,7 @@ run opts = do , statVerbosity , showSource , strict - , stash + , persistWarnings } <- ask let isWorkspacePackage = case _ of @@ -118,11 +118,11 @@ run opts = do , statVerbosity: fromMaybe Psa.defaultParseOptions.statVerbosity statVerbosity , stashFile: do Alternative.guard (not opts.depsOnly) - shouldStashWarnings <- stash + shouldStashWarnings <- persistWarnings Alternative.guard shouldStashWarnings case workspace.selected of - Just p -> Just $ Paths.mkLocalCachesStashFile $ PackageName.print p.package.name - Nothing -> Just Paths.localCachesStashEntireWorkspace + Just p -> Just $ Paths.mkLocalCachesPersistentWarningsFile $ PackageName.print p.package.name + Nothing -> Just Paths.localCachesPersistedWarningsEntireWorkspace } buildBackend globs = do case workspace.backend of diff --git a/spaghetto/src/Spago/Command/Init.purs b/spaghetto/src/Spago/Command/Init.purs index e87bac809..820293e7e 100644 --- a/spaghetto/src/Spago/Command/Init.purs +++ b/spaghetto/src/Spago/Command/Init.purs @@ -94,7 +94,7 @@ defaultConfig name set = , statVerbosity: Nothing , showSource: Nothing , strict: Nothing - , stash: Nothing + , persistWarnings: Nothing } , publish: Nothing , bundle: Nothing diff --git a/spaghetto/src/Spago/Command/Publish.purs b/spaghetto/src/Spago/Command/Publish.purs index 51f5f300f..1d044f4d1 100644 --- a/spaghetto/src/Spago/Command/Publish.purs +++ b/spaghetto/src/Spago/Command/Publish.purs @@ -106,7 +106,7 @@ publish _args = do , statVerbosity: (Nothing :: Maybe Core.StatVerbosity) , showSource: (Nothing :: Maybe Core.ShowSourceCode) , strict: (Nothing :: Maybe Boolean) - , stash: (Nothing :: Maybe Boolean) + , persistWarnings: (Nothing :: Maybe Boolean) } ( Build.run { depsOnly: false @@ -270,7 +270,7 @@ publish _args = do , statVerbosity: (Nothing :: Maybe Core.StatVerbosity) , showSource: (Nothing :: Maybe Core.ShowSourceCode) , strict: (Nothing :: Maybe Boolean) - , stash: (Nothing :: Maybe Boolean) + , persistWarnings: (Nothing :: Maybe Boolean) } ( Build.run { depsOnly: false diff --git a/spaghetto/src/Spago/Config.purs b/spaghetto/src/Spago/Config.purs index 164da770e..2b981a4a0 100644 --- a/spaghetto/src/Spago/Config.purs +++ b/spaghetto/src/Spago/Config.purs @@ -66,7 +66,7 @@ type BuildOptions = , statVerbosity :: Maybe Core.StatVerbosity , showSource :: Maybe Core.ShowSourceCode , strict :: Maybe Boolean - , stash :: Maybe Boolean + , persistWarnings :: Maybe Boolean } fromExtraPackage :: Core.ExtraPackage -> Package @@ -312,7 +312,7 @@ readWorkspace maybeSelectedPackage = do , statVerbosity: _.statVerbosity =<< workspace.build_opts , showSource: _.showSource =<< workspace.build_opts , strict: _.strict =<< workspace.build_opts - , stash: _.stash =<< workspace.build_opts + , persistWarnings: _.persistWarnings =<< workspace.build_opts } pure diff --git a/spaghetto/src/Spago/Paths.purs b/spaghetto/src/Spago/Paths.purs index 3d072ddc0..f68dbd814 100644 --- a/spaghetto/src/Spago/Paths.purs +++ b/spaghetto/src/Spago/Paths.purs @@ -37,11 +37,11 @@ registryPath = Path.concat [ globalCachePath, "registry" ] registryIndexPath ∷ FilePath registryIndexPath = Path.concat [ globalCachePath, "registry-index" ] -localCacheStashesPath :: FilePath -localCacheStashesPath = Path.concat [ localCachePath, "stashes" ] +localCachePersistedWarningsPath :: FilePath +localCachePersistedWarningsPath = Path.concat [ localCachePath, "persisted-warnings" ] -localCachesStashEntireWorkspace :: FilePath -localCachesStashEntireWorkspace = mkLocalCachesStashFile "entire-workspace" +localCachesPersistedWarningsEntireWorkspace :: FilePath +localCachesPersistedWarningsEntireWorkspace = mkLocalCachesPersistentWarningsFile "entire-workspace" -mkLocalCachesStashFile :: String -> FilePath -mkLocalCachesStashFile fileName = Path.concat [ localCacheStashesPath, fileName <> ".stash" ] +mkLocalCachesPersistentWarningsFile :: String -> FilePath +mkLocalCachesPersistentWarningsFile fileName = Path.concat [ localCachePersistedWarningsPath, fileName <> ".stash" ] From 1c4080a48146602244404d4d0aaa4f0c069257a5 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 19 Apr 2023 14:08:53 -0500 Subject: [PATCH 75/78] Update censor build warnings options in readme --- spaghetto/README.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/spaghetto/README.md b/spaghetto/README.md index 5e17ede09..8cfad64fe 100644 --- a/spaghetto/README.md +++ b/spaghetto/README.md @@ -245,12 +245,18 @@ package: # optional build: - # optional, Boolean, censor all warnings - censorWarnings: false - # optional, Boolean, censor warnings from library sources - censorLib: false - # optional, Boolean, censor warnings from project sources - censorSrc: false + # optional, whether to censor warnings from dependency sources, + # project sources, both, or none + censorBuildWarnings: + # one of 4 values: + # 1. Both + "all" + # 2. dependency only + "dependency" + # 3. project only + "project" + # 4. do not censor warnings + "none" # optional, NonEmptyArray, censor specific codes censorCodes: - ShadowedName From bc6db40b63df61b18fb9194c0aea013163464b4d Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 19 Apr 2023 14:09:07 -0500 Subject: [PATCH 76/78] Fix 'details' block --- spaghetto/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spaghetto/README.md b/spaghetto/README.md index 8cfad64fe..f8fe56017 100644 --- a/spaghetto/README.md +++ b/spaghetto/README.md @@ -222,6 +222,8 @@ When ran from the directory `foo`, Spago will search for a "workspace" config fi At the end of this process, `foo` and `baz` are the only packages considered. + + ### `spago.yml` fields and their meaning ```yml From d1a47fcff2c6a55fd4d42eeefe96fdb2b46e7dae Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 19 Apr 2023 14:40:10 -0500 Subject: [PATCH 77/78] Fix typos --- spaghetto/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spaghetto/README.md b/spaghetto/README.md index f8fe56017..c95d5a79f 100644 --- a/spaghetto/README.md +++ b/spaghetto/README.md @@ -240,9 +240,9 @@ package: # One of three options # 1. just the package - packageName - # 2. the package, using the widest possible vesrion range + # 2. the package, using the widest possible version range - packageName: "*" - # 2. the package, using a specified vesrion range + # 2. the package, using a specified version range - packageName: ">=1.1.1 <2.0.0" # optional From 1ace197ef771f58b0228844f65f4de3da854787c Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 19 Apr 2023 14:45:02 -0500 Subject: [PATCH 78/78] Rephrase persist warnings flag description --- spaghetto/bin/src/Flags.purs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spaghetto/bin/src/Flags.purs b/spaghetto/bin/src/Flags.purs index 57e54c118..aa9cd0199 100644 --- a/spaghetto/bin/src/Flags.purs +++ b/spaghetto/bin/src/Flags.purs @@ -64,7 +64,7 @@ statVerbosity = ArgParser.optional $ ArgParser.choose "StatVerbosity" persistWarnings ∷ ArgParser (Maybe Boolean) persistWarnings = - ArgParser.flag [ "--persist-warnings" ] "Enable persistent warnings using default persist-warnings file location" + ArgParser.flag [ "--persist-warnings" ] "Persist the compiler warnings between multiple underlying `purs compile` calls" # ArgParser.boolean # ArgParser.optional