packages feed

scrod 0.2026.2.23 → 0.2026.3.4

raw patch · 11 files changed

+159/−61 lines, 11 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Scrod.Convert.FromGhc: convertArguments :: Maybe ItemKey -> SrcSpan -> [(Text, Maybe (LHsDoc GhcPs))] -> ConvertM [Located Item]
+ Scrod.Convert.FromGhc: convertArgumentsAndReturnType :: Maybe ItemKey -> SrcSpan -> [(Text, Maybe (LHsDoc GhcPs))] -> Maybe (Text, Maybe (LHsDoc GhcPs)) -> ConvertM [Located Item]
+ Scrod.Convert.FromGhc: safeHaskellExtension :: SafeHaskellMode -> Map Extension Bool
+ Scrod.Convert.FromGhc: safeHaskellName :: SafeHaskellMode -> Maybe String
+ Scrod.Ghc.PragmaInfo: MkPragmaInfo :: Maybe Language -> [OnOff Extension] -> SafeHaskellMode -> PragmaInfo
+ Scrod.Ghc.PragmaInfo: [extensions] :: PragmaInfo -> [OnOff Extension]
+ Scrod.Ghc.PragmaInfo: [language] :: PragmaInfo -> Maybe Language
+ Scrod.Ghc.PragmaInfo: [safeHaskell] :: PragmaInfo -> SafeHaskellMode
+ Scrod.Ghc.PragmaInfo: data PragmaInfo
+ Scrod.Ghc.PragmaInfo: instance GHC.Internal.Classes.Eq Scrod.Ghc.PragmaInfo.PragmaInfo
+ Scrod.Ghc.PragmaInfo: instance GHC.Internal.Show.Show Scrod.Ghc.PragmaInfo.PragmaInfo
- Scrod.Convert.FromGhc: fromGhc :: Bool -> ((Maybe Language, [OnOff Extension]), Located (HsModule GhcPs)) -> Either String Module
+ Scrod.Convert.FromGhc: fromGhc :: Bool -> (PragmaInfo, Located (HsModule GhcPs)) -> Either String Module
- Scrod.Ghc.Parse: discoverExtensions :: [Located String] -> StringBuffer -> Either SourceError (Maybe Language, [OnOff Extension])
+ Scrod.Ghc.Parse: discoverExtensions :: [Located String] -> StringBuffer -> Either SourceError ((Maybe Language, [OnOff Extension]), SafeHaskellMode)
- Scrod.Ghc.Parse: discoverExtensionsIO :: [Located String] -> StringBuffer -> IO (Maybe Language, [OnOff Extension])
+ Scrod.Ghc.Parse: discoverExtensionsIO :: [Located String] -> StringBuffer -> IO ((Maybe Language, [OnOff Extension]), SafeHaskellMode)
- Scrod.Ghc.Parse: parse :: Bool -> [String] -> String -> Either String ((Maybe Language, [OnOff Extension]), Located (HsModule GhcPs))
+ Scrod.Ghc.Parse: parse :: Bool -> [String] -> String -> Either String (PragmaInfo, Located (HsModule GhcPs))

Files

CHANGELOG.md view
@@ -1,4 +1,7 @@ # Change log -Scrod follows the [Package Versioning Policy](https://pvp.haskell.org).+Scrod will follow the [Package Versioning Policy](https://pvp.haskell.org).+While at major version 0, Scrod follows [CalVer](https://calver.org) instead.+It uses the scheme `0.YYYY.M.D`.+No stability is expected during this period. You can find release notes [on GitHub](https://github.com/tfausak/scrod/releases).
README.md view
@@ -21,9 +21,10 @@  | Asset | Description | | --- | --- |-| `scrod-*-linux.tar.gz` | Linux binary |-| `scrod-*-darwin.tar.gz` | macOS binary |-| `scrod-*-win32.tar.gz` | Windows binary |+| `scrod-*-linux-x86_64.tar.gz` | Linux x86_64 binary |+| `scrod-*-linux-aarch64.tar.gz` | Linux AArch64 binary |+| `scrod-*-darwin-aarch64.tar.gz` | macOS binary |+| `scrod-*-win32-x86_64.tar.gz` | Windows binary | | `scrod-*.vsix` | VSCode extension for live documentation preview | | `scrod-*-wasm.tar.gz` | WASM build (for use in browsers) | | `scrod-*-wasi.tar.gz` | WASI build (for use with runtimes like Wasmtime) |
scrod.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.12 name: scrod-version: 0.2026.2.23+version: 0.2026.3.4 synopsis: Worse Haskell documentation description:   Scrod generates documentation for Haskell modules, similar to Haddock. Unlike@@ -176,6 +176,7 @@     Scrod.Ghc.ParserOpts     Scrod.Ghc.Platform     Scrod.Ghc.PlatformMisc+    Scrod.Ghc.PragmaInfo     Scrod.Ghc.ToolSettings     Scrod.Ghc.Uninitialized     Scrod.Ghc.UnitId
source/library/Scrod/Convert/FromGhc.hs view
@@ -26,6 +26,7 @@ import qualified GHC.Parser.Annotation as Annotation import qualified GHC.Types.Basic as Basic import qualified GHC.Types.PkgQual as PkgQual+import qualified GHC.Types.SafeHaskell as SafeHaskell import qualified GHC.Types.SourceText as SourceText import qualified GHC.Types.SrcLoc as SrcLoc import qualified GHC.Utils.Outputable as Outputable@@ -72,15 +73,19 @@ import qualified Scrod.Core.Version as Version import qualified Scrod.Core.Warning as Warning import qualified Scrod.Ghc.OnOff as OnOff+import qualified Scrod.Ghc.PragmaInfo as PragmaInfo  -- | Convert a parsed GHC module to the internal 'Module' type. fromGhc ::   Bool ->-  ( (Maybe Session.Language, [DynFlags.OnOff GhcExtension.Extension]),+  ( PragmaInfo.PragmaInfo,     SrcLoc.Located (Hs.HsModule Ghc.GhcPs)   ) ->   Either String Module.Module-fromGhc isSignature ((language, extensions), lHsModule) = do+fromGhc isSignature (pragmaInfo, lHsModule) = do+  let language = PragmaInfo.language pragmaInfo+      extensions = PragmaInfo.extensions pragmaInfo+      safeHaskellMode = PragmaInfo.safeHaskell pragmaInfo   version <- maybe (Left "invalid version") Right $ versionFromBase PackageInfo.version   let (moduleDocumentation, moduleSince) = extractModuleDocAndSince lHsModule       namedDocChunks = extractNamedDocChunks lHsModule@@ -91,7 +96,7 @@     Module.MkModule       { Module.version = version,         Module.language = languageFromGhc <$> language,-        Module.extensions = extensionsToMap extensions,+        Module.extensions = safeHaskellExtension safeHaskellMode <> extensionsToMap extensions,         Module.documentation = moduleDocumentation,         Module.since = moduleSince,         Module.signature = isSignature,@@ -136,6 +141,20 @@   Map.fromListWith (\_ x -> x)     . fmap (Tuple.swap . fmap extensionFromGhc . OnOff.onOff ((,) True) ((,) False)) +-- | Convert a Safe Haskell mode to an extension entry, if applicable.+safeHaskellExtension :: SafeHaskell.SafeHaskellMode -> Map.Map Extension.Extension Bool+safeHaskellExtension mode = case safeHaskellName mode of+  Nothing -> Map.empty+  Just name -> Map.singleton (Extension.MkExtension $ Text.pack name) True++-- | Map a Safe Haskell mode to its extension name.+safeHaskellName :: SafeHaskell.SafeHaskellMode -> Maybe String+safeHaskellName mode = case mode of+  SafeHaskell.Sf_Safe -> Just "Safe"+  SafeHaskell.Sf_Unsafe -> Just "Unsafe"+  SafeHaskell.Sf_Trustworthy -> Just "Trustworthy"+  _ -> Nothing+ -- | Extract module name from the parsed module. extractModuleName ::   SrcLoc.Located (Syntax.HsModule Ghc.GhcPs) ->@@ -442,9 +461,8 @@           case parentResult of             Nothing -> pure []             Just (parentItem, parentKey) -> do-              argItems <- convertArguments (Just parentKey) (Annotation.getLocA lName) args-              retItem <- convertReturnType (Just parentKey) (Annotation.getLocA lName) retType-              pure $ [parentItem] <> argItems <> retItem+              childItems <- convertArgumentsAndReturnType (Just parentKey) (Annotation.getLocA lName) args retType+              pure $ parentItem : childItems   Syntax.PatSynSig _ names _ ->     let sigText = Names.extractSigSignature sig         (args, retType) = SigArguments.extractSigArguments sig@@ -461,9 +479,8 @@           case parentResult of             Nothing -> pure []             Just (parentItem, parentKey) -> do-              argItems <- convertArguments (Just parentKey) (Annotation.getLocA lName) args-              retItem <- convertReturnType (Just parentKey) (Annotation.getLocA lName) retType-              pure $ [parentItem] <> argItems <> retItem+              childItems <- convertArgumentsAndReturnType (Just parentKey) (Annotation.getLocA lName) args retType+              pure $ parentItem : childItems   Syntax.FixSig _ (Syntax.FixitySig _ names (SyntaxBasic.Fixity prec dir)) ->     let fixityDoc = Doc.Paragraph . Doc.String $ fixityDirectionToText dir <> Text.pack (" " <> show prec)         combinedDoc = combineDoc doc fixityDoc@@ -483,16 +500,20 @@      in Maybe.maybeToList <$> Internal.mkItemM (Annotation.getLocA lDecl) Nothing Nothing doc docSince sigText ItemKind.CompletePragma   _ -> Maybe.maybeToList <$> convertDeclWithDocM Nothing doc docSince (Names.extractSigName sig) Nothing lDecl --- | Convert extracted argument data into child Argument items.--- Returns no items if none of the arguments have documentation.-convertArguments ::+-- | Convert extracted argument and return-type data into child items.+-- Shows all arguments and the return type as a group: if any argument+-- or the return type has documentation, all are included; otherwise none.+convertArgumentsAndReturnType ::   Maybe ItemKey.ItemKey ->   SrcLoc.SrcSpan ->   [(Text.Text, Maybe (HsDoc.LHsDoc Ghc.GhcPs))] ->+  Maybe (Text.Text, Maybe (HsDoc.LHsDoc Ghc.GhcPs)) ->   Internal.ConvertM [Located.Located Item.Item]-convertArguments parentKey srcSpan args-  | any (Maybe.isJust . snd) args =-      Maybe.catMaybes <$> traverse (convertOneArgument parentKey srcSpan) args+convertArgumentsAndReturnType parentKey srcSpan args mRet+  | any (Maybe.isJust . snd) args || maybe False (Maybe.isJust . snd) mRet = do+      argItems <- Maybe.catMaybes <$> traverse (convertOneArgument parentKey srcSpan) args+      retItem <- convertReturnType parentKey srcSpan mRet+      pure $ argItems <> retItem   | otherwise = pure []  -- | Convert a single argument to an Argument item.@@ -746,9 +767,8 @@             case parentResult of               Nothing -> pure []               Just (methodItem, methodKey) -> do-                argItems <- convertArguments (Just methodKey) (Annotation.getLocA lName) args-                retItem <- convertReturnType (Just methodKey) (Annotation.getLocA lName) retType-                pure $ [methodItem] <> argItems <> retItem+                childItems <- convertArgumentsAndReturnType (Just methodKey) (Annotation.getLocA lName) args retType+                pure $ methodItem : childItems     _ -> pure []   _ -> pure [] 
source/library/Scrod/Convert/FromGhc/SigArguments.hs view
@@ -18,7 +18,8 @@ -- | Extract argument types and their optional doc comments from a type -- signature. Walks the 'HsFunTy' chain, collecting each argument's -- pretty-printed type text and its 'LHsDoc' (if the argument was wrapped--- in 'HsDocTy'). The return type is included only when it has documentation.+-- in 'HsDocTy'). The return type is always included when the signature has+-- function arrows. -- -- Returns a pair of (arguments, optional return type). --@@ -40,7 +41,7 @@  -- | Skip through 'HsForAllTy' and 'HsQualTy' to reach the arrow chain, -- then extract arguments from the 'HsFunTy' chain. Returns the arguments--- and the optional documented return type separately.+-- and the return type separately. extractArgsFromBody ::   Syntax.LHsType Ghc.GhcPs ->   ( [(Text.Text, Maybe (HsDoc.LHsDoc Ghc.GhcPs))],@@ -57,7 +58,7 @@       let (args, ret) = extractArgsFromBody res        in (extractArg arg : args, ret)     _ -> ([], Just (extractArg lTy))-  _ -> ([], Nothing)+  _ -> ([], Just (extractArg lTy))  -- | Extract the type text and optional doc comment from a single argument. -- If the argument is wrapped in 'HsDocTy', the doc is extracted and the
source/library/Scrod/Convert/ToHtml.hs view
@@ -610,13 +610,13 @@                         Just n -> [element "code" [("class", "text-break")] [Xml.text $ ItemName.unwrap n]]                     )                 ]-                <> earlySignature                 <> [ element                        "div"                        [("class", "mx-1")]                        [ element "span" [("class", "badge " <> badgeColor)] [Xml.string $ kindToString kind]                        ]                    ]+                <> earlySignature                 <> lateSignature                 <> [ element                        "div"
source/library/Scrod/Extra/Builder.hs view
@@ -1,5 +1,3 @@-{- hlint ignore "Avoid restricted extensions" -}-{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskellQuotes #-}  module Scrod.Extra.Builder where@@ -23,49 +21,57 @@ spec :: (Applicative m, Monad n) => Spec.Spec m n -> n () spec s = do   Spec.named s 'toByteString $ do+    let f = toByteString . Builder.stringUtf8+    let b = ByteString.pack+     Spec.it s "works with an empty builder" $ do-      Spec.assertEq s (toByteString "") ""+      Spec.assertEq s (f "") $ b []      Spec.it s "works with one byte" $ do-      Spec.assertEq s (toByteString " \x0 ") " \x0 "+      Spec.assertEq s (f " \x0 ") $ b [0x20, 0x00, 0x20]      Spec.it s "works with two bytes" $ do-      Spec.assertEq s (toByteString " \x80 ") " \xc2\x80 "+      Spec.assertEq s (f " \x80 ") $ b [0x20, 0xc2, 0x80, 0x20]      Spec.it s "works with three bytes" $ do-      Spec.assertEq s (toByteString " \x800 ") " \xe0\xa0\x80 "+      Spec.assertEq s (f " \x800 ") $ b [0x20, 0xe0, 0xa0, 0x80, 0x20]      Spec.it s "works with four bytes" $ do-      Spec.assertEq s (toByteString " \x10000 ") " \xf0\x90\x80\x80 "+      Spec.assertEq s (f " \x10000 ") $ b [0x20, 0xf0, 0x90, 0x80, 0x80, 0x20]    Spec.named s 'toText $ do+    let f = toText . Builder.stringUtf8+    let t = Text.pack+     Spec.it s "works with an empty builder" $ do-      Spec.assertEq s (toText "") ""+      Spec.assertEq s (f "") $ t ""      Spec.it s "works with one byte" $ do-      Spec.assertEq s (toText " \x0 ") " \x0 "+      Spec.assertEq s (f " \x0 ") $ t " \x0 "      Spec.it s "works with two bytes" $ do-      Spec.assertEq s (toText " \x80 ") " \x80 "+      Spec.assertEq s (f " \x80 ") $ t " \x80 "      Spec.it s "works with three bytes" $ do-      Spec.assertEq s (toText " \x800 ") " \x800 "+      Spec.assertEq s (f " \x800 ") $ t " \x800 "      Spec.it s "works with four bytes" $ do-      Spec.assertEq s (toText " \x10000 ") " \x10000 "+      Spec.assertEq s (f " \x10000 ") $ t " \x10000 "    Spec.named s 'toString $ do+    let f = toString . Builder.stringUtf8+     Spec.it s "works with an empty builder" $ do-      Spec.assertEq s (toString "") ""+      Spec.assertEq s (f "") ""      Spec.it s "works with one byte" $ do-      Spec.assertEq s (toString " \x0 ") " \x0 "+      Spec.assertEq s (f " \x0 ") " \x0 "      Spec.it s "works with two bytes" $ do-      Spec.assertEq s (toString " \x80 ") " \x80 "+      Spec.assertEq s (f " \x80 ") " \x80 "      Spec.it s "works with three bytes" $ do-      Spec.assertEq s (toString " \x800 ") " \x800 "+      Spec.assertEq s (f " \x800 ") " \x800 "      Spec.it s "works with four bytes" $ do-      Spec.assertEq s (toString " \x10000 ") " \x10000 "+      Spec.assertEq s (f " \x10000 ") " \x10000 "
source/library/Scrod/Ghc/DynFlags.hs view
@@ -159,7 +159,7 @@       DynFlags.rtsOptsEnabled = Uninitialized.throw 'DynFlags.rtsOptsEnabled,       DynFlags.rtsOptsSuggestions = Uninitialized.throw 'DynFlags.rtsOptsSuggestions,       DynFlags.ruleCheck = Uninitialized.throw 'DynFlags.ruleCheck,-      DynFlags.safeHaskell = SafeHaskell.Sf_Ignore,+      DynFlags.safeHaskell = SafeHaskell.Sf_None,       DynFlags.safeInfer = False,       DynFlags.safeInferred = Uninitialized.throw 'DynFlags.safeInferred,       DynFlags.simplPhases = Uninitialized.throw 'DynFlags.simplPhases,
source/library/Scrod/Ghc/Parse.hs view
@@ -24,6 +24,7 @@ import qualified GHC.Parser as Parser import qualified GHC.Parser.Header as Header import qualified GHC.Parser.Lexer as Lexer+import qualified GHC.Types.SafeHaskell as SafeHaskell import qualified GHC.Types.SourceError as SourceError import qualified GHC.Types.SrcLoc as SrcLoc import qualified GHC.Utils.Logger as Logger@@ -35,6 +36,7 @@ import qualified Scrod.Ghc.DynFlags as DynFlags import qualified Scrod.Ghc.OnOff as OnOff import qualified Scrod.Ghc.ParserOpts as ParserOpts+import qualified Scrod.Ghc.PragmaInfo as PragmaInfo import qualified Scrod.Spec as Spec import qualified System.IO.Unsafe as Unsafe @@ -44,14 +46,14 @@   String ->   Either     String-    ( (Maybe Session.Language, [DynFlags.OnOff Extension.Extension]),+    ( PragmaInfo.PragmaInfo,       SrcLoc.Located (Hs.HsModule Ghc.GhcPs)     ) parse isSignature extraOptions string = do   let originalStringBuffer = StringBuffer.stringToStringBuffer string   let cabalOptions = cabalExtensionOptions string   let options = fmap SrcLoc.noLoc $ extraOptions <> cabalOptions-  languageAndExtensions <- Bifunctor.first Exception.displayException $ discoverExtensions options originalStringBuffer+  (languageAndExtensions, safeHaskellMode) <- Bifunctor.first Exception.displayException $ discoverExtensions options originalStringBuffer   let extensions = uncurry resolveExtensions languageAndExtensions   source <-     if EnumSet.member Extension.Cpp extensions@@ -65,7 +67,15 @@   let parser = if isSignature then Parser.parseSignature else Parser.parseModule   case Lexer.unP parser pState of     Lexer.PFailed newPState -> Left . Outputable.showSDocUnsafe . Outputable.ppr $ Lexer.getPsErrorMessages newPState-    Lexer.POk _ lHsModule -> pure (languageAndExtensions, lHsModule)+    Lexer.POk _ lHsModule ->+      let (lang, exts) = languageAndExtensions+          pragmaInfo =+            PragmaInfo.MkPragmaInfo+              { PragmaInfo.language = lang,+                PragmaInfo.extensions = exts,+                PragmaInfo.safeHaskell = safeHaskellMode+              }+       in pure (pragmaInfo, lHsModule)  cabalExtensionOptions :: String -> [String] cabalExtensionOptions = fmap ("-X" <>) . Cabal.discoverExtensions@@ -75,7 +85,7 @@   StringBuffer.StringBuffer ->   Either     SourceError.SourceError-    (Maybe Flags.Language, [DynFlags.OnOff Extension.Extension])+    ((Maybe Flags.Language, [DynFlags.OnOff Extension.Extension]), SafeHaskell.SafeHaskellMode) discoverExtensions cabalOptions =   Unsafe.unsafePerformIO     . Exception.try@@ -84,11 +94,11 @@ discoverExtensionsIO ::   [SrcLoc.Located String] ->   StringBuffer.StringBuffer ->-  IO (Maybe Flags.Language, [DynFlags.OnOff Extension.Extension])+  IO ((Maybe Flags.Language, [DynFlags.OnOff Extension.Extension]), SafeHaskell.SafeHaskellMode) discoverExtensionsIO cabalOptions stringBuffer = do   logger <- Logger.initLogger   (dynFlags, _, _) <- Session.parseDynamicFilePragma logger DynFlags.empty $ cabalOptions <> discoverOptions stringBuffer-  pure (DynFlags.language dynFlags, DynFlags.extensions dynFlags)+  pure ((DynFlags.language dynFlags, DynFlags.extensions dynFlags), DynFlags.safeHaskell dynFlags)  discoverOptions :: StringBuffer.StringBuffer -> [SrcLoc.Located String] discoverOptions stringBuffer =@@ -112,8 +122,10 @@ spec :: (Applicative m, Monad n) => Spec.Spec m n -> n () spec s = do   Spec.named s 'parse $ do+    let f = PragmaInfo.MkPragmaInfo+     Spec.it s "succeeds with empty input" $ do-      Spec.assertEq s (fst <$> parse False [] "") $ Right (Nothing, [])+      Spec.assertEq s (fst <$> parse False [] "") $ Right (f Nothing [] SafeHaskell.Sf_None)      Spec.it s "fails with invalid input" $ do       Spec.assertEq s (fst <$> parse False [] "!") $ Left "{Resolved: ErrorWithoutFlag\n ErrorWithoutFlag\n   parse error on input `!'}"@@ -122,22 +134,31 @@       Spec.assertEq s (fst <$> parse False [] "{-# language Unknown #-}") $ Left "<interactive>:1:14: error: [GHC-46537]\n    Unsupported extension: Unknown"      Spec.it s "succeeds with a language" $ do-      Spec.assertEq s (fst <$> parse False [] "{-# language Haskell98 #-}") $ Right (Just Session.Haskell98, [])+      Spec.assertEq s (fst <$> parse False [] "{-# language Haskell98 #-}") $ Right (f (Just Session.Haskell98) [] SafeHaskell.Sf_None)      Spec.it s "succeeds with an enabled extension" $ do-      Spec.assertEq s (fst <$> parse False [] "{-# language CPP #-}") $ Right (Nothing, [Session.On Extension.Cpp])+      Spec.assertEq s (fst <$> parse False [] "{-# language CPP #-}") $ Right (f Nothing [Session.On Extension.Cpp] SafeHaskell.Sf_None)      Spec.it s "succeeds with a disabled extension" $ do-      Spec.assertEq s (fst <$> parse False [] "{-# language NoCPP #-}") $ Right (Nothing, [Session.Off Extension.Cpp])+      Spec.assertEq s (fst <$> parse False [] "{-# language NoCPP #-}") $ Right (f Nothing [Session.Off Extension.Cpp] SafeHaskell.Sf_None)      Spec.it s "succeeds with a signature" $ do-      Spec.assertEq s (fst <$> parse True [] "signature Foo where") $ Right (Nothing, [])+      Spec.assertEq s (fst <$> parse True [] "signature Foo where") $ Right (f Nothing [] SafeHaskell.Sf_None)      Spec.it s "succeeds with cabal script header extension" $ do-      Spec.assertEq s (fst <$> parse False [] "{- cabal:\ndefault-extensions: CPP\n-}") $ Right (Nothing, [Session.On Extension.Cpp])+      Spec.assertEq s (fst <$> parse False [] "{- cabal:\ndefault-extensions: CPP\n-}") $ Right (f Nothing [Session.On Extension.Cpp] SafeHaskell.Sf_None)      Spec.it s "succeeds with extra options" $ do-      Spec.assertEq s (fst <$> parse False ["-XOverloadedStrings"] "") $ Right (Nothing, [Session.On Extension.OverloadedStrings])+      Spec.assertEq s (fst <$> parse False ["-XOverloadedStrings"] "") $ Right (f Nothing [Session.On Extension.OverloadedStrings] SafeHaskell.Sf_None)      Spec.it s "succeeds with cabal script header and LANGUAGE pragma" $ do-      Spec.assertEq s (fst <$> parse False [] "{- cabal:\ndefault-extensions: CPP\n-}\n{-# language OverloadedStrings #-}") $ Right (Nothing, [Session.On Extension.OverloadedStrings, Session.On Extension.Cpp])+      Spec.assertEq s (fst <$> parse False [] "{- cabal:\ndefault-extensions: CPP\n-}\n{-# language OverloadedStrings #-}") $ Right (f Nothing [Session.On Extension.OverloadedStrings, Session.On Extension.Cpp] SafeHaskell.Sf_None)++    Spec.it s "succeeds with Safe" $ do+      Spec.assertEq s (fst <$> parse False [] "{-# language Safe #-}") $ Right (f Nothing [] SafeHaskell.Sf_Safe)++    Spec.it s "succeeds with Unsafe" $ do+      Spec.assertEq s (fst <$> parse False [] "{-# language Unsafe #-}") $ Right (f Nothing [] SafeHaskell.Sf_Unsafe)++    Spec.it s "succeeds with Trustworthy" $ do+      Spec.assertEq s (fst <$> parse False [] "{-# language Trustworthy #-}") $ Right (f Nothing [] SafeHaskell.Sf_Trustworthy)
+ source/library/Scrod/Ghc/PragmaInfo.hs view
@@ -0,0 +1,13 @@+module Scrod.Ghc.PragmaInfo where++import qualified GHC.Driver.DynFlags as DynFlags+import qualified GHC.Driver.Session as Session+import qualified GHC.LanguageExtensions.Type as Extension+import qualified GHC.Types.SafeHaskell as SafeHaskell++data PragmaInfo = MkPragmaInfo+  { language :: Maybe Session.Language,+    extensions :: [DynFlags.OnOff Extension.Extension],+    safeHaskell :: SafeHaskell.SafeHaskellMode+  }+  deriving (Eq, Show)
source/library/Scrod/TestSuite/Integration.hs view
@@ -153,6 +153,15 @@         "{-# language NoOverloadedStrings #-}"         [("/extensions/OverloadedStrings", "false")] +    Spec.it s "works with Safe" $ do+      check s "{-# language Safe #-}" [("/extensions/Safe", "true")]++    Spec.it s "works with Unsafe" $ do+      check s "{-# language Unsafe #-}" [("/extensions/Unsafe", "true")]++    Spec.it s "works with Trustworthy" $ do+      check s "{-# language Trustworthy #-}" [("/extensions/Trustworthy", "true")]+   Spec.describe s "documentation" $ do     Spec.it s "defaults to Empty" $ do       check s "" [("/documentation/type", "\"Empty\"")]@@ -2655,11 +2664,34 @@           ("/items/0/value/name", "\"f\""),           ("/items/0/value/signature", "\"a -> a\""),           ("/items/0/value/documentation/type", "\"Empty\""),-          ("/items/1/value/kind/type", "\"ReturnType\""),+          ("/items/1/value/kind/type", "\"Argument\""),           ("/items/1/value/parentKey", "0"),           ("/items/1/value/signature", "\"a\""),+          ("/items/1/value/documentation/type", "\"Empty\""),+          ("/items/2/value/kind/type", "\"ReturnType\""),+          ("/items/2/value/parentKey", "0"),+          ("/items/2/value/signature", "\"a\""),+          ("/items/2/value/documentation/type", "\"Paragraph\""),+          ("/items/2/value/documentation/value/value", "\"lost\"")+        ]++    Spec.it s "function with arg doc but no return doc" $ do+      check+        s+        "f :: a {- ^ x -} -> b"+        [ ("/items/0/value/kind/type", "\"Function\""),+          ("/items/0/value/name", "\"f\""),+          ("/items/0/value/signature", "\"a -> b\""),+          ("/items/0/value/documentation/type", "\"Empty\""),+          ("/items/1/value/kind/type", "\"Argument\""),+          ("/items/1/value/parentKey", "0"),+          ("/items/1/value/signature", "\"a\""),           ("/items/1/value/documentation/type", "\"Paragraph\""),-          ("/items/1/value/documentation/value/value", "\"lost\"")+          ("/items/1/value/documentation/value/value", "\"x \""),+          ("/items/2/value/kind/type", "\"ReturnType\""),+          ("/items/2/value/parentKey", "0"),+          ("/items/2/value/signature", "\"b\""),+          ("/items/2/value/documentation/type", "\"Empty\"")         ]      Spec.it s "data constructor with arg doc has argument children" $ do