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 +4/−1
- README.md +4/−3
- scrod.cabal +2/−1
- source/library/Scrod/Convert/FromGhc.hs +38/−18
- source/library/Scrod/Convert/FromGhc/SigArguments.hs +4/−3
- source/library/Scrod/Convert/ToHtml.hs +1/−1
- source/library/Scrod/Extra/Builder.hs +23/−17
- source/library/Scrod/Ghc/DynFlags.hs +1/−1
- source/library/Scrod/Ghc/Parse.hs +35/−14
- source/library/Scrod/Ghc/PragmaInfo.hs +13/−0
- source/library/Scrod/TestSuite/Integration.hs +34/−2
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