diff --git a/examples/docs/src/DocComments.purs b/examples/docs/src/DocComments.purs new file mode 100644 index 0000000000..4bc2e93953 --- /dev/null +++ b/examples/docs/src/DocComments.purs @@ -0,0 +1,11 @@ +module DocComments where + +-- | This declaration has a code block: +-- | +-- | example == 0 +-- | +-- | Here we are really testing that the leading whitespace is not stripped, as +-- | this ensures that we don't accidentally change code blocks into normal +-- | paragraphs. +example :: Int +example = 0 diff --git a/psc-docs/Main.hs b/psc-docs/Main.hs index ff557bc7d1..a1ca8ec3cd 100644 --- a/psc-docs/Main.hs +++ b/psc-docs/Main.hs @@ -9,6 +9,7 @@ import Control.Category ((>>>)) import Control.Monad.Writer import Data.Text (Text) import qualified Data.Text as T +import qualified Data.Text.IO as T import Data.Function (on) import Data.List import Data.Maybe (fromMaybe) @@ -22,7 +23,7 @@ import qualified Language.PureScript as P import qualified Paths_purescript as Paths import System.Exit (exitFailure) import System.IO (hPutStrLn, hPrint, hSetEncoding, stderr, stdout, utf8) -import System.IO.UTF8 (readUTF8FileT) +import System.IO.UTF8 (readUTF8FileT, writeUTF8FileT) import System.Directory (createDirectoryIfMissing) import System.FilePath (takeDirectory) import System.FilePath.Glob (glob) @@ -65,11 +66,11 @@ docgen (PSCDocsOptions fmt inputGlob output) = do case output of EverythingToStdOut -> - putStrLn (D.runDocs (D.modulesAsMarkdown ms)) + T.putStrLn (D.runDocs (D.modulesAsMarkdown ms)) ToStdOut names -> do let (ms', missing) = takeByName ms names guardMissing missing - putStrLn (D.runDocs (D.modulesAsMarkdown ms')) + T.putStrLn (D.runDocs (D.modulesAsMarkdown ms')) ToFiles names -> do let (ms', missing) = takeByName' ms names guardMissing missing @@ -78,7 +79,7 @@ docgen (PSCDocsOptions fmt inputGlob output) = do forM_ ms'' $ \grp -> do let fp = fst (head grp) createDirectoryIfMissing True (takeDirectory fp) - writeFile fp (D.runDocs (D.modulesAsMarkdown (map snd grp))) + writeUTF8FileT fp (D.runDocs (D.modulesAsMarkdown (map snd grp))) where guardMissing [] = return () diff --git a/psc-publish/Main.hs b/psc-publish/Main.hs index dd8f6632fb..5d2e902bd2 100644 --- a/psc-publish/Main.hs +++ b/psc-publish/Main.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE OverloadedStrings #-} module Main where diff --git a/src/Language/PureScript/Docs/AsMarkdown.hs b/src/Language/PureScript/Docs/AsMarkdown.hs index a336030108..527ca53036 100644 --- a/src/Language/PureScript/Docs/AsMarkdown.hs +++ b/src/Language/PureScript/Docs/AsMarkdown.hs @@ -13,7 +13,9 @@ import Control.Monad.Error.Class (MonadError) import Control.Monad.Writer (Writer, tell, execWriter) import Data.Foldable (for_) +import Data.Monoid ((<>)) import Data.List (partition) +import Data.Text (Text) import qualified Data.Text as T import Language.PureScript.Docs.RenderedCode @@ -24,12 +26,12 @@ import qualified Language.PureScript.Docs.Render as Render -- | -- Take a list of modules and render them all in order, returning a single --- Markdown-formatted String. +-- Markdown-formatted Text. -- renderModulesAsMarkdown :: (MonadError P.MultipleErrors m) => [P.Module] -> - m String + m Text renderModulesAsMarkdown = fmap (runDocs . modulesAsMarkdown) . Convert.convertModules @@ -38,13 +40,13 @@ modulesAsMarkdown = mapM_ moduleAsMarkdown moduleAsMarkdown :: Module -> Docs moduleAsMarkdown Module{..} = do - headerLevel 2 $ "Module " ++ T.unpack (P.runModuleName modName) + headerLevel 2 $ "Module " <> P.runModuleName modName spacer for_ modComments tell' mapM_ (declAsMarkdown modName) modDeclarations spacer for_ modReExports $ \(mn, decls) -> do - headerLevel 3 $ "Re-exported from " ++ T.unpack (P.runModuleName mn) ++ ":" + headerLevel 3 $ "Re-exported from " <> P.runModuleName mn <> ":" spacer mapM_ (declAsMarkdown mn) decls @@ -71,7 +73,7 @@ declAsMarkdown mn decl@Declaration{..} = do isChildInstance (ChildInstance _ _) = True isChildInstance _ = False -codeToString :: RenderedCode -> String +codeToString :: RenderedCode -> Text codeToString = outputWith elemAsMarkdown where elemAsMarkdown (Syntax x) = x @@ -95,14 +97,14 @@ codeToString = outputWith elemAsMarkdown -- P.Infixr -> "right-associative" -- P.Infix -> "non-associative" -childToString :: First -> ChildDeclaration -> String +childToString :: First -> ChildDeclaration -> Text childToString f decl@ChildDeclaration{..} = case cdeclInfo of ChildDataConstructor _ -> let c = if f == First then "=" else "|" - in " " ++ c ++ " " ++ str + in " " <> c <> " " <> str ChildTypeClassMember _ -> - " " ++ str + " " <> str ChildInstance _ _ -> str where @@ -113,19 +115,19 @@ data First | NotFirst deriving (Show, Eq, Ord) -type Docs = Writer [String] () +type Docs = Writer [Text] () -runDocs :: Docs -> String -runDocs = unlines . execWriter +runDocs :: Docs -> Text +runDocs = T.unlines . execWriter -tell' :: String -> Docs +tell' :: Text -> Docs tell' = tell . (:[]) spacer :: Docs spacer = tell' "" -headerLevel :: Int -> String -> Docs -headerLevel level hdr = tell' (replicate level '#' ++ ' ' : hdr) +headerLevel :: Int -> Text -> Docs +headerLevel level hdr = tell' (T.replicate level "#" <> " " <> hdr) fencedBlock :: Docs -> Docs fencedBlock inner = do @@ -133,5 +135,5 @@ fencedBlock inner = do inner tell' "```" -ticks :: String -> String -ticks = ("`" ++) . (++ "`") +ticks :: Text -> Text +ticks = ("`" <>) . (<> "`") diff --git a/src/Language/PureScript/Docs/Convert.hs b/src/Language/PureScript/Docs/Convert.hs index 5473cffb2c..34920e7b8d 100644 --- a/src/Language/PureScript/Docs/Convert.hs +++ b/src/Language/PureScript/Docs/Convert.hs @@ -16,7 +16,7 @@ import Control.Monad.Error.Class (MonadError) import Control.Monad.State (runStateT) import Control.Monad.Writer.Strict (runWriterT) import qualified Data.Map as Map -import qualified Data.Text as T +import Data.Text (Text) import Language.PureScript.Docs.Convert.ReExports (updateReExports) import Language.PureScript.Docs.Convert.Single (convertSingleModule, collectBookmarks) @@ -167,9 +167,9 @@ insertValueTypes env m = err msg = P.internalError ("Docs.Convert.insertValueTypes: " ++ msg) -runParser :: P.TokenParser a -> String -> Either String a +runParser :: P.TokenParser a -> Text -> Either String a runParser p s = either (Left . show) Right $ do - ts <- P.lex "" (T.pack s) + ts <- P.lex "" s P.runTokenParser "" (p <* eof) ts -- | diff --git a/src/Language/PureScript/Docs/Convert/ReExports.hs b/src/Language/PureScript/Docs/Convert/ReExports.hs index f4fcec2b3e..ee6d379eb6 100644 --- a/src/Language/PureScript/Docs/Convert/ReExports.hs +++ b/src/Language/PureScript/Docs/Convert/ReExports.hs @@ -4,7 +4,7 @@ module Language.PureScript.Docs.Convert.ReExports import Prelude.Compat -import Control.Arrow ((&&&), first, second) +import Control.Arrow ((&&&), second) import Control.Monad import Control.Monad.Reader.Class (MonadReader, ask) import Control.Monad.State.Class (MonadState, gets, modify) @@ -16,6 +16,7 @@ import Data.Map (Map) import Data.Maybe (mapMaybe) import Data.Monoid ((<>)) import qualified Data.Map as Map +import Data.Text (Text) import qualified Data.Text as T import Language.PureScript.Docs.Types @@ -184,12 +185,12 @@ lookupValueDeclaration :: MonadReader P.ModuleName m) => P.ModuleName -> P.Ident -> - m (P.ModuleName, [Either (String, P.Constraint, ChildDeclaration) Declaration]) + m (P.ModuleName, [Either (Text, P.Constraint, ChildDeclaration) Declaration]) lookupValueDeclaration importedFrom ident = do decls <- lookupModuleDeclarations "lookupValueDeclaration" importedFrom let rs = - filter (\d -> declTitle d == T.unpack (P.showIdent ident) + filter (\d -> declTitle d == P.showIdent ident && (isValue d || isValueAlias d)) decls errOther other = internalErrorInModule @@ -215,7 +216,7 @@ lookupValueDeclaration importedFrom ident = do (declChildren d)) matchesIdent cdecl = - cdeclTitle cdecl == T.unpack (P.showIdent ident) + cdeclTitle cdecl == P.showIdent ident matchesAndIsTypeClassMember = uncurry (&&) . (matchesIdent &&& isTypeClassMember) @@ -239,7 +240,7 @@ lookupValueOpDeclaration -> m (P.ModuleName, [Declaration]) lookupValueOpDeclaration importedFrom op = do decls <- lookupModuleDeclarations "lookupValueOpDeclaration" importedFrom - case filter (\d -> declTitle d == T.unpack (P.showOp op) && isValueAlias d) decls of + case filter (\d -> declTitle d == P.showOp op && isValueAlias d) decls of [d] -> pure (importedFrom, [d]) other -> @@ -259,7 +260,7 @@ lookupTypeDeclaration :: lookupTypeDeclaration importedFrom ty = do decls <- lookupModuleDeclarations "lookupTypeDeclaration" importedFrom let - ds = filter (\d -> declTitle d == T.unpack (P.runProperName ty) && isType d) decls + ds = filter (\d -> declTitle d == P.runProperName ty && isType d) decls case ds of [d] -> pure (importedFrom, [d]) @@ -275,7 +276,7 @@ lookupTypeOpDeclaration lookupTypeOpDeclaration importedFrom tyOp = do decls <- lookupModuleDeclarations "lookupTypeOpDeclaration" importedFrom let - ds = filter (\d -> declTitle d == ("type " ++ T.unpack (P.showOp tyOp)) && isTypeAlias d) decls + ds = filter (\d -> declTitle d == ("type " <> P.showOp tyOp) && isTypeAlias d) decls case ds of [d] -> pure (importedFrom, [d]) @@ -291,7 +292,7 @@ lookupTypeClassDeclaration lookupTypeClassDeclaration importedFrom tyClass = do decls <- lookupModuleDeclarations "lookupTypeClassDeclaration" importedFrom let - ds = filter (\d -> declTitle d == T.unpack (P.runProperName tyClass) + ds = filter (\d -> declTitle d == P.runProperName tyClass && isTypeClass d) decls case ds of @@ -324,7 +325,7 @@ lookupModuleDeclarations definedIn moduleName = do handleTypeClassMembers :: (MonadReader P.ModuleName m) => - Map P.ModuleName [Either (String, P.Constraint, ChildDeclaration) Declaration] -> + Map P.ModuleName [Either (Text, P.Constraint, ChildDeclaration) Declaration] -> Map P.ModuleName [Declaration] -> m (Map P.ModuleName [Declaration], Map P.ModuleName [Declaration]) handleTypeClassMembers valsAndMembers typeClasses = @@ -339,7 +340,7 @@ handleTypeClassMembers valsAndMembers typeClasses = |> fmap splitMap valsAndMembersToEnv :: - [Either (String, P.Constraint, ChildDeclaration) Declaration] -> TypeClassEnv + [Either (Text, P.Constraint, ChildDeclaration) Declaration] -> TypeClassEnv valsAndMembersToEnv xs = let (envUnhandledMembers, envValues) = partitionEithers xs envTypeClasses = [] @@ -360,11 +361,11 @@ typeClassesToEnv classes = -- data TypeClassEnv = TypeClassEnv { -- | - -- Type class members which have not yet been dealt with. The String is the + -- Type class members which have not yet been dealt with. The Text is the -- name of the type class they belong to, and the constraint is used to -- make sure that they have the correct type if they get promoted. -- - envUnhandledMembers :: [(String, P.Constraint, ChildDeclaration)] + envUnhandledMembers :: [(Text, P.Constraint, ChildDeclaration)] -- | -- A list of normal value declarations. Type class members will be added to -- this list if their parent type class is not available. @@ -428,7 +429,7 @@ handleEnv TypeClassEnv{..} = _ -> internalErrorInModule ("handleEnv: Bad child declaration passed to promoteChild: " - ++ cdeclTitle) + ++ T.unpack cdeclTitle) addConstraint constraint = P.quantify . P.moveQuantifiersToFront . P.ConstrainedType [constraint] @@ -448,7 +449,7 @@ filterDataConstructors -> Map P.ModuleName [Declaration] -> Map P.ModuleName [Declaration] filterDataConstructors = - filterExportedChildren isDataConstructor (T.unpack . P.runProperName) + filterExportedChildren isDataConstructor P.runProperName -- | -- Given a list of exported type class member names, remove any data @@ -460,12 +461,12 @@ filterTypeClassMembers -> Map P.ModuleName [Declaration] -> Map P.ModuleName [Declaration] filterTypeClassMembers = - filterExportedChildren isTypeClassMember (T.unpack . P.showIdent) + filterExportedChildren isTypeClassMember P.showIdent filterExportedChildren :: (Functor f) => (ChildDeclaration -> Bool) - -> (name -> String) + -> (name -> Text) -> [name] -> f [Declaration] -> f [Declaration] @@ -504,7 +505,7 @@ typeClassConstraintFor :: Declaration -> Maybe P.Constraint typeClassConstraintFor Declaration{..} = case declInfo of TypeClassDeclaration tyArgs _ _ -> - Just (P.Constraint (P.Qualified Nothing (P.ProperName (T.pack declTitle))) (mkConstraint (map (first T.pack) tyArgs)) Nothing) + Just (P.Constraint (P.Qualified Nothing (P.ProperName declTitle)) (mkConstraint tyArgs) Nothing) _ -> Nothing where diff --git a/src/Language/PureScript/Docs/Convert/Single.hs b/src/Language/PureScript/Docs/Convert/Single.hs index c6d630011d..c111c18947 100644 --- a/src/Language/PureScript/Docs/Convert/Single.hs +++ b/src/Language/PureScript/Docs/Convert/Single.hs @@ -5,13 +5,12 @@ module Language.PureScript.Docs.Convert.Single import Prelude.Compat -import Control.Arrow (first) import Control.Category ((>>>)) import Control.Monad import Data.Either import Data.List (nub) -import Data.Maybe (mapMaybe) +import Data.Maybe (mapMaybe, fromMaybe) import Data.Monoid ((<>)) import Data.Text (Text) import qualified Data.Text as T @@ -19,8 +18,6 @@ import qualified Data.Text as T import Language.PureScript.Docs.Types import qualified Language.PureScript as P --- TODO (Christoph): Get rid of the T.unpack s - -- | -- Convert a single Module, but ignore re-exports; any re-exported types or -- values will not appear in the result. @@ -46,14 +43,14 @@ convertSingleModule m@(P.Module _ coms moduleName _ _) = -- In the second pass, we go over all of the Left values and augment the -- relevant declarations, leaving only the augmented Right values. -- --- Note that in the Left case, we provide a [String] as well as augment --- information. The [String] value should be a list of titles of declarations +-- Note that in the Left case, we provide a [Text] as well as augment +-- information. The [Text] value should be a list of titles of declarations -- that the augmentation should apply to. For example, for a type instance -- declaration, that would be any types or type classes mentioned in the -- instance. For a fixity declaration, it would be just the relevant operator's -- name. type IntermediateDeclaration - = Either ([String], DeclarationAugment) Declaration + = Either ([Text], DeclarationAugment) Declaration -- | Some data which will be used to augment a Declaration in the -- output. @@ -97,7 +94,7 @@ getDeclarationTitle _ = Nothing -- | Create a basic Declaration value. mkDeclaration :: Text -> DeclarationInfo -> Declaration mkDeclaration title info = - Declaration { declTitle = T.unpack title + Declaration { declTitle = title , declComments = Nothing , declSourceSpan = Nothing , declChildren = [] @@ -119,27 +116,27 @@ convertDeclaration (P.ExternDeclaration _ ty) title = convertDeclaration (P.DataDeclaration dtype _ args ctors) title = Just (Right (mkDeclaration title info) { declChildren = children }) where - info = DataDeclaration dtype (map (first T.unpack) args) + info = DataDeclaration dtype args children = map convertCtor ctors convertCtor (ctor', tys) = - ChildDeclaration (T.unpack (P.runProperName ctor')) Nothing Nothing (ChildDataConstructor tys) + ChildDeclaration (P.runProperName ctor') Nothing Nothing (ChildDataConstructor tys) convertDeclaration (P.ExternDataDeclaration _ kind') title = basicDeclaration title (ExternDataDeclaration kind') convertDeclaration (P.TypeSynonymDeclaration _ args ty) title = - basicDeclaration title (TypeSynonymDeclaration (map (first T.unpack) args) ty) + basicDeclaration title (TypeSynonymDeclaration args ty) convertDeclaration (P.TypeClassDeclaration _ args implies fundeps ds) title = Just (Right (mkDeclaration title info) { declChildren = children }) where - info = TypeClassDeclaration (map (first T.unpack) args) implies (convertFundepsToStrings args fundeps) + info = TypeClassDeclaration args implies (convertFundepsToStrings args fundeps) children = map convertClassMember ds convertClassMember (P.PositionedDeclaration _ _ d) = convertClassMember d convertClassMember (P.TypeDeclaration ident' ty) = - ChildDeclaration (T.unpack (P.showIdent ident')) Nothing Nothing (ChildTypeClassMember ty) + ChildDeclaration (P.showIdent ident') Nothing Nothing (ChildTypeClassMember ty) convertClassMember _ = P.internalError "convertDeclaration: Invalid argument to convertClassMember." convertDeclaration (P.TypeInstanceDeclaration _ constraints className tys _) title = - Just (Left (T.unpack classNameString : map T.unpack typeNameStrings, AugmentChild childDecl)) + Just (Left (classNameString : typeNameStrings, AugmentChild childDecl)) where classNameString = unQual className typeNameStrings = nub (concatMap (P.everythingOnTypes (++) extractProperNames) tys) @@ -148,7 +145,7 @@ convertDeclaration (P.TypeInstanceDeclaration _ constraints className tys _) tit extractProperNames (P.TypeConstructor n) = [unQual n] extractProperNames _ = [] - childDecl = ChildDeclaration (T.unpack title) Nothing Nothing (ChildInstance constraints classApp) + childDecl = ChildDeclaration title Nothing Nothing (ChildInstance constraints classApp) classApp = foldl P.TypeApp (P.TypeConstructor (fmap P.coerceProperName className)) tys convertDeclaration (P.ValueFixityDeclaration fixity (P.Qualified mn alias) _) title = Just $ Right $ mkDeclaration title (AliasDeclaration fixity (P.Qualified mn (Right alias))) @@ -172,25 +169,24 @@ convertDeclaration (P.PositionedDeclaration srcSpan com d') title = withAugmentChild f (t, AugmentChild d) = (t, AugmentChild (f d)) convertDeclaration _ _ = Nothing -convertComments :: [P.Comment] -> Maybe String +convertComments :: [P.Comment] -> Maybe Text convertComments cs = do let raw = concatMap toLines cs let docs = mapMaybe stripPipe raw guard (not (null docs)) - pure (unlines docs) + pure (T.unlines docs) where - toLines (P.LineComment s) = [T.unpack s] - toLines (P.BlockComment s) = lines (T.unpack s) - - stripPipe s' = - case dropWhile (== ' ') s' of - ('|':' ':s) -> - Just s - ('|':s) -> - Just s - _ -> - Nothing + toLines (P.LineComment s) = [s] + toLines (P.BlockComment s) = T.lines s + + stripPipe = + T.dropWhile (== ' ') + >>> T.stripPrefix "|" + >>> fmap (dropPrefix " ") + + dropPrefix prefix str = + fromMaybe str (T.stripPrefix prefix str) -- | Go through a PureScript module and extract a list of Bookmarks; references -- to data types or values, to be used as a kind of index. These are used for @@ -199,8 +195,7 @@ collectBookmarks :: InPackage P.Module -> [Bookmark] collectBookmarks (Local m) = map Local (collectBookmarks' m) collectBookmarks (FromDep pkg m) = map (FromDep pkg) (collectBookmarks' m) -collectBookmarks' :: P.Module -> [(P.ModuleName, String)] +collectBookmarks' :: P.Module -> [(P.ModuleName, Text)] collectBookmarks' m = map (P.getModuleName m, ) - (mapMaybe (fmap T.unpack . getDeclarationTitle) - (P.exportedDeclarations m)) + (mapMaybe getDeclarationTitle (P.exportedDeclarations m)) diff --git a/src/Language/PureScript/Docs/Prim.hs b/src/Language/PureScript/Docs/Prim.hs index 845073799a..308587b7a0 100644 --- a/src/Language/PureScript/Docs/Prim.hs +++ b/src/Language/PureScript/Docs/Prim.hs @@ -2,7 +2,7 @@ module Language.PureScript.Docs.Prim (primDocsModule) where import Prelude.Compat hiding (fail) -import Control.Arrow (first) +import Data.Text (Text) import qualified Data.Text as T import qualified Data.Map as Map import Language.PureScript.Docs.Types @@ -30,18 +30,18 @@ primDocsModule = Module } unsafeLookup :: forall v (a :: P.ProperNameType). - Map.Map (P.Qualified (P.ProperName a)) v -> String -> String -> v -unsafeLookup m errorMsg ty = go ty + Map.Map (P.Qualified (P.ProperName a)) v -> String -> Text -> v +unsafeLookup m errorMsg name = go name where - go = fromJust' . flip Map.lookup m . P.primName . T.pack + go = fromJust' . flip Map.lookup m . P.primName fromJust' (Just x) = x - fromJust' _ = P.internalError $ errorMsg ++ ty + fromJust' _ = P.internalError $ errorMsg ++ show name -lookupPrimKind :: String -> P.Kind +lookupPrimKind :: Text -> P.Kind lookupPrimKind = fst . unsafeLookup P.primTypes "Docs.Prim: No such Prim type: " -primType :: String -> String -> Declaration +primType :: Text -> Text -> Declaration primType title comments = Declaration { declTitle = title , declComments = Just comments @@ -52,10 +52,10 @@ primType title comments = Declaration -- | Lookup the TypeClassData of a Prim class. This function is specifically -- not exported because it is partial. -lookupPrimClass :: String -> P.TypeClassData +lookupPrimClass :: Text -> P.TypeClassData lookupPrimClass = unsafeLookup P.primClasses "Docs.Prim: No such Prim class: " -primClass :: String -> String -> Declaration +primClass :: Text -> Text -> Declaration primClass title comments = Declaration { declTitle = title , declComments = Just comments @@ -68,11 +68,11 @@ primClass title comments = Declaration superclasses = P.typeClassSuperclasses tcd fundeps = convertFundepsToStrings args (P.typeClassDependencies tcd) in - TypeClassDeclaration (map (first T.unpack) args) superclasses fundeps + TypeClassDeclaration args superclasses fundeps } function :: Declaration -function = primType "Function" $ unlines +function = primType "Function" $ T.unlines [ "A function, which takes values of the type specified by the first type" , "parameter, and returns values of the type specified by the second." , "In the JavaScript backend, this is a standard JavaScript Function." @@ -91,7 +91,7 @@ function = primType "Function" $ unlines ] array :: Declaration -array = primType "Array" $ unlines +array = primType "Array" $ T.unlines [ "An Array: a data structure supporting efficient random access. In" , "the JavaScript backend, values of this type are represented as JavaScript" , "Arrays at runtime." @@ -102,7 +102,7 @@ array = primType "Array" $ unlines ] record :: Declaration -record = primType "Record" $ unlines +record = primType "Record" $ T.unlines [ "The type of records whose fields are known at compile time. In the" , "JavaScript backend, values of this type are represented as JavaScript" , "Objects at runtime." @@ -118,7 +118,7 @@ record = primType "Record" $ unlines ] number :: Declaration -number = primType "Number" $ unlines +number = primType "Number" $ T.unlines [ "A double precision floating point number (IEEE 754)." , "" , "Construct values of this type with literals:" @@ -128,7 +128,7 @@ number = primType "Number" $ unlines ] int :: Declaration -int = primType "Int" $ unlines +int = primType "Int" $ T.unlines [ "A 32-bit signed integer. See the purescript-integers package for details" , "of how this is accomplished when compiling to JavaScript." , "" @@ -138,7 +138,7 @@ int = primType "Int" $ unlines ] string :: Declaration -string = primType "String" $ unlines +string = primType "String" $ T.unlines [ "A String. As in JavaScript, String values represent sequences of UTF-16" , "code units, which are not required to form a valid encoding of Unicode" , "text (for example, lone surrogates are permitted)." @@ -151,7 +151,7 @@ string = primType "String" $ unlines ] char :: Declaration -char = primType "Char" $ unlines +char = primType "Char" $ T.unlines [ "A single character (UTF-16 code unit). The JavaScript representation is a" , "normal String, which is guaranteed to contain one code unit. This means" , "that astral plane characters (i.e. those with code point values greater" @@ -163,21 +163,21 @@ char = primType "Char" $ unlines ] boolean :: Declaration -boolean = primType "Boolean" $ unlines +boolean = primType "Boolean" $ T.unlines [ "A JavaScript Boolean value." , "" , "Construct values of this type with the literals `true` and `false`." ] partial :: Declaration -partial = primClass "Partial" $ unlines +partial = primClass "Partial" $ T.unlines [ "The Partial type class is used to indicate that a function is *partial,*" , "that is, it will throw an error for some inputs. For more information," , "see [the Partial type class guide](https://github.com/purescript/documentation/blob/master/guides/The-Partial-type-class.md)." ] fail :: Declaration -fail = primClass "Fail" $ unlines +fail = primClass "Fail" $ T.unlines [ "The Fail type class is part of the custom type errors feature. To provide" , "a custom type error when someone tries to use a particular instance," , "write that instance out with a Fail constraint." @@ -187,7 +187,7 @@ fail = primClass "Fail" $ unlines ] typeConcat :: Declaration -typeConcat = primType "TypeConcat" $ unlines +typeConcat = primType "TypeConcat" $ T.unlines [ "The TypeConcat type constructor concatenates two Symbols in a custom type" , "error." , "" @@ -196,7 +196,7 @@ typeConcat = primType "TypeConcat" $ unlines ] typeString :: Declaration -typeString = primType "TypeString" $ unlines +typeString = primType "TypeString" $ T.unlines [ "The TypeString type constructor renders any concrete type into a Symbol" , "in a custom type error." , "" diff --git a/src/Language/PureScript/Docs/Render.hs b/src/Language/PureScript/Docs/Render.hs index 352bff910e..f9fa3a804d 100644 --- a/src/Language/PureScript/Docs/Render.hs +++ b/src/Language/PureScript/Docs/Render.hs @@ -13,16 +13,14 @@ import Prelude.Compat import Data.Maybe (maybeToList) import Data.Monoid ((<>)) -import qualified Data.Text as T import Data.Text (Text) +import qualified Data.Text as T import Language.PureScript.Docs.RenderedCode import Language.PureScript.Docs.Types import Language.PureScript.Docs.Utils.MonoidExtras import qualified Language.PureScript as P --- TODO (Christoph): get rid of T.unpack's - renderDeclaration :: Declaration -> RenderedCode renderDeclaration = renderDeclarationWithOptions defaultRenderTypeOptions @@ -35,7 +33,7 @@ renderDeclarationWithOptions opts Declaration{..} = , renderType' ty ] DataDeclaration dtype args -> - [ keyword (T.unpack (P.showDataDeclType dtype)) + [ keyword (P.showDataDeclType dtype) , renderType' (typeApp declTitle args) ] ExternDataDeclaration kind' -> @@ -76,7 +74,7 @@ renderDeclarationWithOptions opts Declaration{..} = AliasDeclaration (P.Fixity associativity precedence) for@(P.Qualified _ alias) -> [ keywordFixity associativity - , syntax $ show precedence + , syntax $ T.pack $ show precedence , ident $ renderQualAlias for , keyword "as" , ident $ adjustAliasName alias declTitle @@ -86,10 +84,10 @@ renderDeclarationWithOptions opts Declaration{..} = renderType' :: P.Type -> RenderedCode renderType' = renderTypeWithOptions opts - renderQualAlias :: FixityAlias -> String + renderQualAlias :: FixityAlias -> Text renderQualAlias (P.Qualified mn alias) - | mn == currentModule opts = T.unpack (renderAlias id alias) - | otherwise = T.unpack (renderAlias (\f -> P.showQualified f . P.Qualified mn) alias) + | mn == currentModule opts = renderAlias id alias + | otherwise = renderAlias (\f -> P.showQualified f . P.Qualified mn) alias renderAlias :: (forall a. (a -> Text) -> a -> Text) @@ -99,8 +97,7 @@ renderDeclarationWithOptions opts Declaration{..} = = either (("type " <>) . f P.runProperName) $ either (f P.runIdent) (f P.runProperName) - -- adjustAliasName (P.AliasType{}) title = drop 6 (init title) - adjustAliasName _ title = tail (init title) + adjustAliasName _ title = T.tail (T.init title) renderChildDeclaration :: ChildDeclaration -> RenderedCode renderChildDeclaration = renderChildDeclarationWithOptions defaultRenderTypeOptions @@ -146,15 +143,15 @@ renderConstraintsWithOptions opts constraints mintersperse (syntax "," <> sp) (map (renderConstraintWithOptions opts) constraints) -notQualified :: String -> P.Qualified (P.ProperName a) -notQualified = P.Qualified Nothing . P.ProperName . T.pack +notQualified :: Text -> P.Qualified (P.ProperName a) +notQualified = P.Qualified Nothing . P.ProperName -typeApp :: String -> [(String, Maybe P.Kind)] -> P.Type +typeApp :: Text -> [(Text, Maybe P.Kind)] -> P.Type typeApp title typeArgs = foldl P.TypeApp (P.TypeConstructor (notQualified title)) (map toTypeVar typeArgs) -toTypeVar :: (String, Maybe P.Kind) -> P.Type -toTypeVar (s, Nothing) = P.TypeVar (T.pack s) -toTypeVar (s, Just k) = P.KindedType (P.TypeVar (T.pack s)) k +toTypeVar :: (Text, Maybe P.Kind) -> P.Type +toTypeVar (s, Nothing) = P.TypeVar s +toTypeVar (s, Just k) = P.KindedType (P.TypeVar s) k diff --git a/src/Language/PureScript/Docs/RenderedCode/Render.hs b/src/Language/PureScript/Docs/RenderedCode/Render.hs index bae5544378..281cd6b2b1 100644 --- a/src/Language/PureScript/Docs/RenderedCode/Render.hs +++ b/src/Language/PureScript/Docs/RenderedCode/Render.hs @@ -14,10 +14,9 @@ import Prelude.Compat import Data.Maybe (fromMaybe) import Data.Monoid ((<>)) -import qualified Data.Text as T import Data.Text (Text) -import Control.Arrow ((<+>), first) +import Control.Arrow ((<+>)) import Control.PatternArrows as PA import Language.PureScript.Crash @@ -35,7 +34,7 @@ typeLiterals = mkPattern match match TypeWildcard{} = Just (syntax "_") match (TypeVar var) = - Just (ident (T.unpack var)) + Just (ident var) match (PrettyPrintObject row) = Just $ mintersperse sp [ syntax "{" @@ -43,7 +42,7 @@ typeLiterals = mkPattern match , syntax "}" ] match (TypeConstructor (Qualified mn name)) = - Just (ctor (T.unpack (runProperName name)) (maybeToContainingModule mn)) + Just (ctor (runProperName name) (maybeToContainingModule mn)) match REmpty = Just (syntax "()") match row@RCons{} = @@ -51,7 +50,7 @@ typeLiterals = mkPattern match match (BinaryNoParensType op l r) = Just $ renderTypeAtom l <> sp <> renderTypeAtom op <> sp <> renderTypeAtom r match (TypeOp (Qualified mn op)) = - Just (ident' (T.unpack (runOpName op)) (maybeToContainingModule mn)) + Just (ident' (runOpName op) (maybeToContainingModule mn)) match _ = Nothing @@ -76,16 +75,14 @@ renderConstraints deps ty = -- Render code representing a Row -- renderRow :: Type -> RenderedCode -renderRow = uncurry renderRow' . convertString . rowToList +renderRow = uncurry renderRow' . rowToList where - convertString :: ([(Text, Type)], Type) -> ([(String, Type)], Type) - convertString = first (map (first T.unpack)) renderRow' h t = renderHead h <> renderTail t -renderHead :: [(String, Type)] -> RenderedCode +renderHead :: [(Text, Type)] -> RenderedCode renderHead = mintersperse (syntax "," <> sp) . map renderLabel -renderLabel :: (String, Type) -> RenderedCode +renderLabel :: (Text, Type) -> RenderedCode renderLabel (label, ty) = mintersperse sp [ ident label @@ -145,10 +142,10 @@ matchType = buildPrettyPrinter operators matchTypeAtom , [ Wrap explicitParens $ \_ ty -> ty ] ] -forall_ :: Pattern () Type ([String], Type) +forall_ :: Pattern () Type ([Text], Type) forall_ = mkPattern match where - match (PrettyPrintForAll idents ty) = Just (map T.unpack idents, ty) + match (PrettyPrintForAll idents ty) = Just (idents, ty) match _ = Nothing insertPlaceholders :: RenderTypeOptions -> Type -> Type @@ -180,7 +177,7 @@ preprocessType opts = dePrim . insertPlaceholders opts -- Render code representing a Kind -- renderKind :: Kind -> RenderedCode -renderKind = kind . T.unpack . prettyPrintKind +renderKind = kind . prettyPrintKind -- | -- Render code representing a Type, as it should appear inside parentheses diff --git a/src/Language/PureScript/Docs/RenderedCode/Types.hs b/src/Language/PureScript/Docs/RenderedCode/Types.hs index 05bd8a1008..074a5a1bc3 100644 --- a/src/Language/PureScript/Docs/RenderedCode/Types.hs +++ b/src/Language/PureScript/Docs/RenderedCode/Types.hs @@ -37,7 +37,7 @@ import Control.Monad.Error.Class (MonadError(..)) import Data.Aeson.BetterErrors import qualified Data.Aeson as A -import qualified Data.Text as T +import Data.Text (Text) import qualified Language.PureScript as P @@ -46,11 +46,11 @@ import qualified Language.PureScript as P -- multiple output formats. For example, plain text, or highlighted HTML. -- data RenderedCodeElement - = Syntax String - | Ident String ContainingModule - | Ctor String ContainingModule - | Kind String - | Keyword String + = Syntax Text + | Ident Text ContainingModule + | Ctor Text ContainingModule + | Kind Text + | Keyword Text | Space deriving (Show, Eq, Ord) @@ -66,9 +66,9 @@ instance A.ToJSON RenderedCodeElement where toJSON (Keyword str) = A.toJSON ["keyword", str] toJSON Space = - A.toJSON ["space" :: String] + A.toJSON ["space" :: Text] -asRenderedCodeElement :: Parse String RenderedCodeElement +asRenderedCodeElement :: Parse Text RenderedCodeElement asRenderedCodeElement = a Syntax "syntax" <|> asIdent <|> @@ -80,14 +80,14 @@ asRenderedCodeElement = where p <|> q = catchError p (const q) - a ctor' ctorStr = ctor' <$> (nth 0 (withString (eq ctorStr)) *> nth 1 asString) - asIdent = nth 0 (withString (eq "ident")) *> (Ident <$> nth 1 asString <*> nth 2 asContainingModule) - asCtor = nth 0 (withString (eq "ctor")) *> (Ctor <$> nth 1 asString <*> nth 2 asContainingModule) - asSpace = nth 0 (withString (eq "space")) *> pure Space + a ctor' ctorStr = ctor' <$> (nth 0 (withText (eq ctorStr)) *> nth 1 asText) + asIdent = nth 0 (withText (eq "ident")) *> (Ident <$> nth 1 asText <*> nth 2 asContainingModule) + asCtor = nth 0 (withText (eq "ctor")) *> (Ctor <$> nth 1 asText <*> nth 2 asContainingModule) + asSpace = nth 0 (withText (eq "space")) *> pure Space eq s s' = if s == s' then Right () else Left "" - unableToParse = withString (Left . show) + unableToParse = withText Left -- | -- This type is isomorphic to 'Maybe' 'P.ModuleName'. It makes code a bit easier @@ -103,7 +103,7 @@ instance A.ToJSON ContainingModule where asContainingModule :: Parse e ContainingModule asContainingModule = - maybeToContainingModule <$> perhaps (P.moduleNameFromString . T.pack <$> asString) + maybeToContainingModule <$> perhaps (P.moduleNameFromString <$> asText) -- | -- Convert a 'Maybe' 'P.ModuleName' to a 'ContainingModule', using the obvious @@ -139,7 +139,7 @@ newtype RenderedCode instance A.ToJSON RenderedCode where toJSON (RC elems) = A.toJSON elems -asRenderedCode :: Parse String RenderedCode +asRenderedCode :: Parse Text RenderedCode asRenderedCode = RC <$> eachInArray asRenderedCodeElement -- | @@ -157,22 +157,22 @@ outputWith f = foldMap f . unRC sp :: RenderedCode sp = RC [Space] -syntax :: String -> RenderedCode +syntax :: Text -> RenderedCode syntax x = RC [Syntax x] -ident :: String -> RenderedCode +ident :: Text -> RenderedCode ident x = RC [Ident x ThisModule] -ident' :: String -> ContainingModule -> RenderedCode +ident' :: Text -> ContainingModule -> RenderedCode ident' x m = RC [Ident x m] -ctor :: String -> ContainingModule -> RenderedCode +ctor :: Text -> ContainingModule -> RenderedCode ctor x m = RC [Ctor x m] -kind :: String -> RenderedCode +kind :: Text -> RenderedCode kind x = RC [Kind x] -keyword :: String -> RenderedCode +keyword :: Text -> RenderedCode keyword kw = RC [Keyword kw] keywordForall :: RenderedCode diff --git a/src/Language/PureScript/Docs/Types.hs b/src/Language/PureScript/Docs/Types.hs index 5de0b1a4a0..dd116d7818 100644 --- a/src/Language/PureScript/Docs/Types.hs +++ b/src/Language/PureScript/Docs/Types.hs @@ -9,12 +9,11 @@ import Prelude.Compat import Control.Arrow (first, (***)) import Control.Monad (when) -import Data.Bifunctor (bimap) import Data.Aeson ((.=)) import Data.Aeson.BetterErrors import Data.ByteString.Lazy (ByteString) import Data.Either (isLeft, isRight) -import Data.Maybe (mapMaybe) +import Data.Maybe (mapMaybe, fromMaybe) import Data.Text (Text) import Data.Version import qualified Data.Vector as V @@ -38,7 +37,7 @@ import Language.PureScript.Docs.RenderedCode as ReExports data Package a = Package { pkgMeta :: PackageMeta , pkgVersion :: Version - , pkgVersionTag :: String + , pkgVersionTag :: Text , pkgModules :: [Module] , pkgBookmarks :: [Bookmark] , pkgResolvedDependencies :: [(PackageName, Version)] @@ -73,7 +72,7 @@ packageName = bowerName . pkgMeta data Module = Module { modName :: P.ModuleName - , modComments :: Maybe String + , modComments :: Maybe Text , modDeclarations :: [Declaration] -- Re-exported values from other modules , modReExports :: [(P.ModuleName, [Declaration])] @@ -81,8 +80,8 @@ data Module = Module deriving (Show, Eq, Ord) data Declaration = Declaration - { declTitle :: String - , declComments :: Maybe String + { declTitle :: Text + , declComments :: Maybe Text , declSourceSpan :: Maybe P.SourceSpan , declChildren :: [ChildDeclaration] , declInfo :: DeclarationInfo @@ -109,7 +108,7 @@ data DeclarationInfo -- newtype) and its type arguments. Constructors are represented as child -- declarations. -- - | DataDeclaration P.DataDeclType [(String, Maybe P.Kind)] + | DataDeclaration P.DataDeclType [(Text, Maybe P.Kind)] -- | -- A data type foreign import, with its kind. @@ -119,13 +118,13 @@ data DeclarationInfo -- | -- A type synonym, with its type arguments and its type. -- - | TypeSynonymDeclaration [(String, Maybe P.Kind)] P.Type + | TypeSynonymDeclaration [(Text, Maybe P.Kind)] P.Type -- | -- A type class, with its type arguments, its superclasses and functional -- dependencies. Instances and members are represented as child declarations. -- - | TypeClassDeclaration [(String, Maybe P.Kind)] [P.Constraint] [([String], [String])] + | TypeClassDeclaration [(Text, Maybe P.Kind)] [P.Constraint] [([Text], [Text])] -- | -- An operator alias declaration, with the member the alias is for and the @@ -134,14 +133,13 @@ data DeclarationInfo | AliasDeclaration P.Fixity FixityAlias deriving (Show, Eq, Ord) -convertFundepsToStrings :: [(Text, Maybe P.Kind)] -> [P.FunctionalDependency] -> [([String], [String])] +convertFundepsToStrings :: [(Text, Maybe P.Kind)] -> [P.FunctionalDependency] -> [([Text], [Text])] convertFundepsToStrings args fundeps = - map (bimap (map T.unpack) (map T.unpack)) fundeps' + map (\(P.FunctionalDependency from to) -> toArgs from to) fundeps where - fundeps' = map (\(P.FunctionalDependency from to) -> toArgs from to) fundeps argsVec = V.fromList (map fst args) getArg i = - maybe + fromMaybe (P.internalError $ unlines [ "convertDeclaration: Functional dependency index" , show i @@ -150,12 +148,12 @@ convertFundepsToStrings args fundeps = , "Functional dependencies are" , show fundeps ] - ) id $ argsVec V.!? i + ) $ argsVec V.!? i toArgs from to = (map getArg from, map getArg to) type FixityAlias = P.Qualified (Either (P.ProperName 'P.TypeName) (Either P.Ident (P.ProperName 'P.ConstructorName))) -declInfoToString :: DeclarationInfo -> String +declInfoToString :: DeclarationInfo -> Text declInfoToString (ValueDeclaration _) = "value" declInfoToString (DataDeclaration _ _) = "data" declInfoToString (ExternDataDeclaration _) = "externData" @@ -201,8 +199,8 @@ filterChildren p decl = decl { declChildren = filter p (declChildren decl) } data ChildDeclaration = ChildDeclaration - { cdeclTitle :: String - , cdeclComments :: Maybe String + { cdeclTitle :: Text + , cdeclComments :: Maybe Text , cdeclSourceSpan :: Maybe P.SourceSpan , cdeclInfo :: ChildDeclarationInfo } @@ -227,7 +225,7 @@ data ChildDeclarationInfo | ChildTypeClassMember P.Type deriving (Show, Eq, Ord) -childDeclInfoToString :: ChildDeclarationInfo -> String +childDeclInfoToString :: ChildDeclarationInfo -> Text childDeclInfoToString (ChildInstance _ _) = "instance" childDeclInfoToString (ChildDataConstructor _) = "dataConstructor" childDeclInfoToString (ChildTypeClassMember _) = "typeClassMember" @@ -245,11 +243,11 @@ isDataConstructor ChildDeclaration{..} = _ -> False newtype GithubUser - = GithubUser { runGithubUser :: String } + = GithubUser { runGithubUser :: Text } deriving (Show, Eq, Ord) newtype GithubRepo - = GithubRepo { runGithubRepo :: String } + = GithubRepo { runGithubRepo :: Text } deriving (Show, Eq, Ord) data PackageError @@ -258,14 +256,14 @@ data PackageError -- parser, and actual version used. | ErrorInPackageMeta BowerError | InvalidVersion - | InvalidDeclarationType String - | InvalidChildDeclarationType String + | InvalidDeclarationType Text + | InvalidChildDeclarationType Text | InvalidFixity - | InvalidKind String - | InvalidDataDeclType String + | InvalidKind Text + | InvalidDataDeclType Text deriving (Show, Eq, Ord) -type Bookmark = InPackage (P.ModuleName, String) +type Bookmark = InPackage (P.ModuleName, Text) data InPackage a = Local a @@ -307,7 +305,7 @@ asPackage minimumVersion uploader = do Package <$> key "packageMeta" asPackageMeta .! ErrorInPackageMeta <*> key "version" asVersion - <*> key "versionTag" asString + <*> key "versionTag" asText <*> key "modules" (eachInArray asModule) <*> key "bookmarks" asBookmarks .! ErrorInPackageMeta <*> key "resolvedDependencies" asResolvedDependencies @@ -338,15 +336,15 @@ displayPackageError e = case e of InvalidVersion -> "Invalid version" InvalidDeclarationType str -> - "Invalid declaration type: \"" <> T.pack str <> "\"" + "Invalid declaration type: \"" <> str <> "\"" InvalidChildDeclarationType str -> - "Invalid child declaration type: \"" <> T.pack str <> "\"" + "Invalid child declaration type: \"" <> str <> "\"" InvalidFixity -> "Invalid fixity" InvalidKind str -> - "Invalid kind: \"" <> T.pack str <> "\"" + "Invalid kind: \"" <> str <> "\"" InvalidDataDeclType str -> - "Invalid data declaration type: \"" <> T.pack str <> "\"" + "Invalid data declaration type: \"" <> str <> "\"" where (<>) = T.append @@ -355,7 +353,7 @@ instance A.FromJSON a => A.FromJSON (Package a) where (asPackage (Version [0,0,0,0] []) fromAesonParser) asGithubUser :: Parse e GithubUser -asGithubUser = GithubUser <$> asString +asGithubUser = GithubUser <$> asText instance A.FromJSON GithubUser where parseJSON = toAesonParser' asGithubUser @@ -372,14 +370,14 @@ parseVersion' str = asModule :: Parse PackageError Module asModule = Module <$> key "name" (P.moduleNameFromString <$> asText) - <*> key "comments" (perhaps asString) + <*> key "comments" (perhaps asText) <*> key "declarations" (eachInArray asDeclaration) <*> key "reExports" (eachInArray asReExport) asDeclaration :: Parse PackageError Declaration asDeclaration = - Declaration <$> key "title" asString - <*> key "comments" (perhaps asString) + Declaration <$> key "title" asText + <*> key "comments" (perhaps asText) <*> key "sourceSpan" (perhaps asSourceSpan) <*> key "children" (eachInArray asChildDeclaration) <*> key "info" asDeclarationInfo @@ -417,7 +415,7 @@ asAssociativity = withString (maybe (Left InvalidFixity) Right . parseAssociativ asDeclarationInfo :: Parse PackageError DeclarationInfo asDeclarationInfo = do - ty <- key "declType" asString + ty <- key "declType" asText case ty of "value" -> ValueDeclaration <$> key "type" asType @@ -439,10 +437,10 @@ asDeclarationInfo = do other -> throwCustomError (InvalidDeclarationType other) -asTypeArguments :: Parse PackageError [(String, Maybe P.Kind)] +asTypeArguments :: Parse PackageError [(Text, Maybe P.Kind)] asTypeArguments = eachInArray asTypeArgument where - asTypeArgument = (,) <$> nth 0 asString <*> nth 1 (perhaps asKind) + asTypeArgument = (,) <$> nth 0 asText <*> nth 1 (perhaps asKind) asKind :: Parse e P.Kind asKind = fromAesonParser @@ -450,28 +448,28 @@ asKind = fromAesonParser asType :: Parse e P.Type asType = fromAesonParser -asFunDeps :: Parse PackageError [([String], [String])] +asFunDeps :: Parse PackageError [([Text], [Text])] asFunDeps = eachInArray asFunDep where - asFunDep = (,) <$> nth 0 (eachInArray asString) <*> nth 1 (eachInArray asString) + asFunDep = (,) <$> nth 0 (eachInArray asText) <*> nth 1 (eachInArray asText) asDataDeclType :: Parse PackageError P.DataDeclType asDataDeclType = - withString $ \s -> case s of + withText $ \s -> case s of "data" -> Right P.Data "newtype" -> Right P.Newtype other -> Left (InvalidDataDeclType other) asChildDeclaration :: Parse PackageError ChildDeclaration asChildDeclaration = - ChildDeclaration <$> key "title" asString - <*> key "comments" (perhaps asString) + ChildDeclaration <$> key "title" asText + <*> key "comments" (perhaps asText) <*> key "sourceSpan" (perhaps asSourceSpan) <*> key "info" asChildDeclarationInfo asChildDeclarationInfo :: Parse PackageError ChildDeclarationInfo asChildDeclarationInfo = do - ty <- key "declType" asString + ty <- key "declType" asText case ty of "instance" -> ChildInstance <$> key "dependencies" (eachInArray asConstraint) @@ -504,7 +502,7 @@ asBookmarks = eachInArray asBookmark asBookmark :: Parse BowerError Bookmark asBookmark = asInPackage ((,) <$> nth 0 (P.moduleNameFromString <$> asText) - <*> nth 1 asString) + <*> nth 1 asText) asResolvedDependencies :: Parse PackageError [(PackageName, Version)] asResolvedDependencies = @@ -514,8 +512,8 @@ asResolvedDependencies = mapLeft _ (Right x) = Right x asGithub :: Parse e (GithubUser, GithubRepo) -asGithub = (,) <$> nth 0 (GithubUser <$> asString) - <*> nth 1 (GithubRepo <$> asString) +asGithub = (,) <$> nth 0 (GithubUser <$> asText) + <*> nth 1 (GithubRepo <$> asText) asSourceSpan :: Parse e P.SourceSpan asSourceSpan = P.SourceSpan <$> key "name" asString diff --git a/src/Language/PureScript/Publish.hs b/src/Language/PureScript/Publish.hs index 83589ba484..e3cecd364b 100644 --- a/src/Language/PureScript/Publish.hs +++ b/src/Language/PureScript/Publish.hs @@ -23,7 +23,7 @@ module Language.PureScript.Publish import Prelude () import Prelude.Compat hiding (userError) -import Control.Arrow ((***)) +import Control.Arrow ((***), first) import Control.Category ((>>>)) import Control.Exception (catch, try) import Control.Monad.Error.Class (MonadError(..)) @@ -35,12 +35,13 @@ import Data.Aeson.BetterErrors import Data.Char (isSpace) import Data.Foldable (traverse_) import Data.Function (on) -import Data.List (stripPrefix, isSuffixOf, (\\), nubBy) +import Data.List (stripPrefix, (\\), nubBy) import Data.List.NonEmpty (NonEmpty(..)) import Data.List.Split (splitOn) import Data.Maybe import Data.Version import qualified Data.SPDX as SPDX +import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.Lazy as TL import qualified Data.Text.Lazy.Encoding as TL @@ -65,7 +66,7 @@ import qualified Language.PureScript.Docs as D data PublishOptions = PublishOptions { -- | How to obtain the version tag and version that the data being -- generated will refer to. - publishGetVersion :: PrepareM (String, Version) + publishGetVersion :: PrepareM (Text, Version) , -- | What to do when the working tree is dirty publishWorkingTreeDirty :: PrepareM () } @@ -184,13 +185,13 @@ checkCleanWorkingTree opts = do unless (status == Clean) $ publishWorkingTreeDirty opts -getVersionFromGitTag :: PrepareM (String, Version) +getVersionFromGitTag :: PrepareM (Text, Version) getVersionFromGitTag = do out <- readProcess' "git" ["tag", "--list", "--points-at", "HEAD"] "" let vs = map trimWhitespace (lines out) case mapMaybe parseMay vs of [] -> userError TagMustBeCheckedOut - [x] -> return x + [x] -> return (first T.pack x) xs -> userError (AmbiguousVersions (map snd xs)) where trimWhitespace = @@ -209,7 +210,7 @@ getBowerRepositoryInfo = either (userError . BadRepositoryField) return . tryExt Just Repository{..} -> do unless (repositoryType == "git") (Left (BadRepositoryType repositoryType)) - maybe (Left NotOnGithub) Right (extractGithub repositoryUrl) + maybe (Left NotOnGithub) Right (extractGithub (T.pack repositoryUrl)) checkLicense :: PackageMeta -> PrepareM () checkLicense pkgMeta = @@ -226,9 +227,9 @@ checkLicense pkgMeta = isValidSPDX :: String -> Bool isValidSPDX = (== 1) . length . SPDX.parseExpression -extractGithub :: String -> Maybe (D.GithubUser, D.GithubRepo) +extractGithub :: Text -> Maybe (D.GithubUser, D.GithubRepo) extractGithub = stripGitHubPrefixes - >>> fmap (splitOn "/") + >>> fmap (T.splitOn "/") >=> takeTwo >>> fmap (D.GithubUser *** (D.GithubRepo . dropDotGit)) @@ -237,18 +238,18 @@ extractGithub = stripGitHubPrefixes takeTwo [x, y] = Just (x, y) takeTwo _ = Nothing - stripGitHubPrefixes :: String -> Maybe String + stripGitHubPrefixes :: Text -> Maybe Text stripGitHubPrefixes = stripPrefixes [ "git://github.com/" , "https://github.com/" , "git@github.com:" ] - stripPrefixes :: [String] -> String -> Maybe String - stripPrefixes prefixes str = msum $ (`stripPrefix` str) <$> prefixes + stripPrefixes :: [Text] -> Text -> Maybe Text + stripPrefixes prefixes str = msum $ (`T.stripPrefix` str) <$> prefixes - dropDotGit :: String -> String + dropDotGit :: Text -> Text dropDotGit str - | ".git" `isSuffixOf` str = take (length str - 4) str + | ".git" `T.isSuffixOf` str = T.take (T.length str - 4) str | otherwise = str readProcess' :: String -> [String] -> String -> PrepareM String @@ -265,12 +266,12 @@ data DependencyStatus -- _resolution key. This can be caused by adding the dependency using -- `bower link`, or simply copying it into bower_components instead of -- installing it normally. - | ResolvedOther String - -- ^ Resolved, but to something other than a version. The String argument + | ResolvedOther Text + -- ^ Resolved, but to something other than a version. The Text argument -- is the resolution type. The values it can take that I'm aware of are -- "commit" and "branch". - | ResolvedVersion String - -- ^ Resolved to a version. The String argument is the resolution tag (eg, + | ResolvedVersion Text + -- ^ Resolved to a version. The Text argument is the resolution tag (eg, -- "v0.1.0"). deriving (Show, Eq) @@ -341,9 +342,9 @@ asDependencyStatus = do else key "pkgMeta" $ keyOrDefault "_resolution" NoResolution $ do - type_ <- key "type" asString + type_ <- key "type" asText case type_ of - "version" -> ResolvedVersion <$> key "tag" asString + "version" -> ResolvedVersion <$> key "tag" asText other -> return (ResolvedOther other) warnUndeclared :: [PackageName] -> [PackageName] -> PrepareM () @@ -374,15 +375,16 @@ handleDeps deps = do bowerDir pkgName = "bower_components/" ++ runPackageName pkgName -- Try to extract a version, and warn if unsuccessful. + tryExtractVersion' :: (PackageName, Text) -> PrepareM (Maybe (PackageName, Version)) tryExtractVersion' pair = maybe (warn (UnacceptableVersion pair) >> return Nothing) (return . Just) (tryExtractVersion pair) -tryExtractVersion :: (PackageName, String) -> Maybe (PackageName, Version) +tryExtractVersion :: (PackageName, Text) -> Maybe (PackageName, Version) tryExtractVersion (pkgName, tag) = - let tag' = fromMaybe tag (stripPrefix "v" tag) - in (pkgName,) <$> D.parseVersion' tag' + let tag' = fromMaybe tag (T.stripPrefix "v" tag) + in (pkgName,) <$> D.parseVersion' (T.unpack tag') -- | Returns whether it looks like there is a purescript package checked out -- in the given directory. diff --git a/src/Language/PureScript/Publish/ErrorsWarnings.hs b/src/Language/PureScript/Publish/ErrorsWarnings.hs index db7d7de173..3e6cf02104 100644 --- a/src/Language/PureScript/Publish/ErrorsWarnings.hs +++ b/src/Language/PureScript/Publish/ErrorsWarnings.hs @@ -24,6 +24,7 @@ import Data.Maybe import Data.Monoid import Data.Version import qualified Data.List.NonEmpty as NonEmpty +import Data.Text (Text) import qualified Data.Text as T import Language.PureScript.Publish.BoxesHelpers @@ -43,7 +44,7 @@ data PackageError data PackageWarning = NoResolvedVersion PackageName | UndeclaredDependency PackageName - | UnacceptableVersion (PackageName, String) + | UnacceptableVersion (PackageName, Text) | DirtyWorkingTree_Warn deriving (Show) @@ -311,7 +312,7 @@ displayOtherError e = case e of data CollectedWarnings = CollectedWarnings { noResolvedVersions :: [PackageName] , undeclaredDependencies :: [PackageName] - , unacceptableVersions :: [(PackageName, String)] + , unacceptableVersions :: [(PackageName, Text)] , dirtyWorkingTree :: Any } deriving (Show, Eq, Ord) @@ -387,7 +388,7 @@ warnUndeclaredDependencies pkgNames = ]) : bulletedList runPackageName (NonEmpty.toList pkgNames) -warnUnacceptableVersions :: NonEmpty (PackageName, String) -> Box +warnUnacceptableVersions :: NonEmpty (PackageName, Text) -> Box warnUnacceptableVersions pkgs = let singular = NonEmpty.length pkgs == 1 pl a b = if singular then b else a @@ -414,7 +415,7 @@ warnUnacceptableVersions pkgs = ]) ] where - showTuple (pkgName, tag) = runPackageName pkgName ++ "#" ++ tag + showTuple (pkgName, tag) = runPackageName pkgName ++ "#" ++ T.unpack tag warnDirtyWorkingTree :: Box warnDirtyWorkingTree = diff --git a/tests/TestDocs.hs b/tests/TestDocs.hs index c68943750e..c260935034 100644 --- a/tests/TestDocs.hs +++ b/tests/TestDocs.hs @@ -1,6 +1,7 @@ {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ViewPatterns #-} {-# LANGUAGE DataKinds #-} +{-# LANGUAGE OverloadedStrings #-} module TestDocs where @@ -13,6 +14,7 @@ import Data.Monoid import Data.Maybe (fromMaybe) import Data.List ((\\)) import Data.Foldable +import Data.Text (Text) import qualified Data.Text as T import System.Exit @@ -37,7 +39,7 @@ main = pushd "examples/docs" $ do case res of Left e -> Publish.printErrorToStdout e >> exitFailure Right Docs.Package{..} -> - forM_ testCases $ \(P.moduleNameFromString . T.pack -> mn, pragmas) -> + forM_ testCases $ \(P.moduleNameFromString -> mn, pragmas) -> let mdl = takeJust ("module not found in docs: " ++ T.unpack (P.runModuleName mn)) (find ((==) mn . Docs.modName) pkgModules) in forM_ pragmas (`runAssertionIO` mdl) @@ -49,25 +51,28 @@ takeJust msg = fromMaybe (error msg) data Assertion -- | Assert that a particular declaration is documented with the given -- children - = ShouldBeDocumented P.ModuleName String [String] + = ShouldBeDocumented P.ModuleName Text [Text] -- | Assert that a particular declaration is not documented - | ShouldNotBeDocumented P.ModuleName String + | ShouldNotBeDocumented P.ModuleName Text -- | Assert that a particular declaration exists, but without a particular -- child. - | ChildShouldNotBeDocumented P.ModuleName String String + | ChildShouldNotBeDocumented P.ModuleName Text Text -- | Assert that a particular declaration has a particular type class -- constraint. - | ShouldBeConstrained P.ModuleName String String + | ShouldBeConstrained P.ModuleName Text Text -- | Assert that a particular typeclass declaration has a functional -- dependency list. - | ShouldHaveFunDeps P.ModuleName String [([String],[String])] + | ShouldHaveFunDeps P.ModuleName Text [([Text],[Text])] -- | Assert that a particular value declaration exists, and its type -- satisfies the given predicate. - | ValueShouldHaveTypeSignature P.ModuleName String (ShowFn (P.Type -> Bool)) + | ValueShouldHaveTypeSignature P.ModuleName Text (ShowFn (P.Type -> Bool)) -- | Assert that a particular type alias exists, and its corresponding -- type, when rendered, matches a given string exactly -- fields: module, type synonym name, expected type - | TypeSynonymShouldRenderAs P.ModuleName String String + | TypeSynonymShouldRenderAs P.ModuleName Text Text + -- | Assert that a documented declaration includes a documentation comment + -- containing a particular string + | ShouldHaveDocComment P.ModuleName Text Text deriving (Show) newtype ShowFn a = ShowFn a @@ -77,28 +82,31 @@ instance Show (ShowFn a) where data AssertionFailure -- | A declaration was not documented, but should have been - = NotDocumented P.ModuleName String + = NotDocumented P.ModuleName Text -- | A child declaration was not documented, but should have been - | ChildrenNotDocumented P.ModuleName String [String] + | ChildrenNotDocumented P.ModuleName Text [Text] -- | A declaration was documented, but should not have been - | Documented P.ModuleName String + | Documented P.ModuleName Text -- | A child declaration was documented, but should not have been - | ChildDocumented P.ModuleName String String + | ChildDocumented P.ModuleName Text Text -- | A constraint was missing. - | ConstraintMissing P.ModuleName String String + | ConstraintMissing P.ModuleName Text Text -- | A functional dependency was missing. - | FunDepMissing P.ModuleName String [([String], [String])] + | FunDepMissing P.ModuleName Text [([Text], [Text])] -- | A declaration had the wrong "type" (ie, value, type, type class) -- Fields: declaration title, expected "type", actual "type". - | WrongDeclarationType P.ModuleName String String String + | WrongDeclarationType P.ModuleName Text Text Text -- | A value declaration had the wrong type (in the sense of "type -- checking"), eg, because the inferred type was used when the explicit type -- should have been. -- Fields: module name, declaration name, actual type. - | ValueDeclarationWrongType P.ModuleName String P.Type + | ValueDeclarationWrongType P.ModuleName Text P.Type -- | A Type synonym has been rendered in an unexpected format -- Fields: module name, declaration name, expected rendering, actual rendering - | TypeSynonymMismatch P.ModuleName String String String + | TypeSynonymMismatch P.ModuleName Text Text Text + -- | A doc comment was not found or did not match what was expected + -- Fields: declaration title, expected substring, actual comments + | DocCommentMissing P.ModuleName Text (Maybe Text) deriving (Show) data AssertionResult @@ -135,62 +143,56 @@ runAssertion assertion Docs.Module{..} = Fail (NotDocumented mn decl) ShouldBeConstrained mn decl tyClass -> - case find ((==) decl . Docs.declTitle) (declarationsFor mn) of - Nothing -> - Fail (NotDocumented mn decl) - Just Docs.Declaration{..} -> - case declInfo of - Docs.ValueDeclaration ty -> - if checkConstrained ty tyClass - then Pass - else Fail (ConstraintMissing mn decl tyClass) - _ -> - Fail (WrongDeclarationType mn decl "value" - (Docs.declInfoToString declInfo)) + findDecl mn decl $ \Docs.Declaration{..} -> + case declInfo of + Docs.ValueDeclaration ty -> + if checkConstrained ty tyClass + then Pass + else Fail (ConstraintMissing mn decl tyClass) + _ -> + Fail (WrongDeclarationType mn decl "value" + (Docs.declInfoToString declInfo)) ShouldHaveFunDeps mn decl fds -> - case find ((==) decl . Docs.declTitle) (declarationsFor mn) of - Nothing -> - Fail (NotDocumented mn decl) - Just Docs.Declaration{..} -> - case declInfo of - Docs.TypeClassDeclaration _ _ fundeps -> - if fundeps == fds - then Pass - else Fail (FunDepMissing mn decl fds) - _ -> - Fail (WrongDeclarationType mn decl "value" - (Docs.declInfoToString declInfo)) + findDecl mn decl $ \Docs.Declaration{..} -> + case declInfo of + Docs.TypeClassDeclaration _ _ fundeps -> + if fundeps == fds + then Pass + else Fail (FunDepMissing mn decl fds) + _ -> + Fail (WrongDeclarationType mn decl "value" + (Docs.declInfoToString declInfo)) ValueShouldHaveTypeSignature mn decl (ShowFn tyPredicate) -> - case find ((==) decl . Docs.declTitle) (declarationsFor mn) of - Nothing -> - Fail (NotDocumented mn decl) - Just Docs.Declaration{..} -> - case declInfo of - Docs.ValueDeclaration ty -> - if tyPredicate ty - then Pass - else Fail - (ValueDeclarationWrongType mn decl ty) - _ -> - Fail (WrongDeclarationType mn decl "value" - (Docs.declInfoToString declInfo)) + findDecl mn decl $ \Docs.Declaration{..} -> + case declInfo of + Docs.ValueDeclaration ty -> + if tyPredicate ty + then Pass + else Fail + (ValueDeclarationWrongType mn decl ty) + _ -> + Fail (WrongDeclarationType mn decl "value" + (Docs.declInfoToString declInfo)) TypeSynonymShouldRenderAs mn decl expected -> - case find ((==) decl . Docs.declTitle) (declarationsFor mn) of - Nothing -> - Fail (NotDocumented mn decl) - Just Docs.Declaration{..} -> - case declInfo of - Docs.TypeSynonymDeclaration [] ty -> - let actual = codeToString (Docs.renderType ty) in - if actual == expected - then Pass - else Fail (TypeSynonymMismatch mn decl expected actual) - _ -> - Fail (WrongDeclarationType mn decl "synonym" - (Docs.declInfoToString declInfo)) + findDecl mn decl $ \Docs.Declaration{..} -> + case declInfo of + Docs.TypeSynonymDeclaration [] ty -> + let actual = codeToString (Docs.renderType ty) in + if actual == expected + then Pass + else Fail (TypeSynonymMismatch mn decl expected actual) + _ -> + Fail (WrongDeclarationType mn decl "synonym" + (Docs.declInfoToString declInfo)) + + ShouldHaveDocComment mn decl expected -> + findDecl mn decl $ \Docs.Declaration{..} -> + if maybe False (expected `T.isInfixOf`) declComments + then Pass + else Fail (DocCommentMissing mn decl declComments) where declarationsFor mn = @@ -201,9 +203,16 @@ runAssertion assertion Docs.Module{..} = findChildren title = fmap childrenTitles . find ((==) title . Docs.declTitle) + findDecl mn title f = + case find ((==) title . Docs.declTitle) (declarationsFor mn) of + Nothing -> + Fail (NotDocumented mn title) + Just decl -> + f decl + childrenTitles = map Docs.cdeclTitle . Docs.declChildren -checkConstrained :: P.Type -> String -> Bool +checkConstrained :: P.Type -> Text -> Bool checkConstrained ty tyClass = -- Note that we don't recurse on ConstrainedType if none of the constraints -- match; this is by design, as constraints should be moved to the front @@ -217,7 +226,7 @@ checkConstrained ty tyClass = False where matches className = - (==) className . T.unpack . P.runProperName . P.disqualify . P.constraintClass + (==) className . P.runProperName . P.disqualify . P.constraintClass runAssertionIO :: Assertion -> Docs.Module -> IO () runAssertionIO assertion mdl = do @@ -228,7 +237,7 @@ runAssertionIO assertion mdl = do putStrLn ("Failed: " <> show reason) exitFailure -testCases :: [(String, [Assertion])] +testCases :: [(Text, [Assertion])] testCases = [ ("Example", [ -- From dependencies @@ -319,6 +328,10 @@ testCases = , ValueShouldHaveTypeSignature (n "TypeOpAliases") "test4" (renderedType "forall a b c d. ((a ~> b) ~> c) ~> d") , ValueShouldHaveTypeSignature (n "TypeOpAliases") "third" (renderedType "forall a b c. a × b × c -> c") ]) + + , ("DocComments", + [ ShouldHaveDocComment (n "DocComments") "example" " example == 0" + ]) ] where diff --git a/tests/TestPrimDocs.hs b/tests/TestPrimDocs.hs index ba73ed7e60..10462b78a0 100644 --- a/tests/TestPrimDocs.hs +++ b/tests/TestPrimDocs.hs @@ -3,7 +3,6 @@ module TestPrimDocs where import Control.Monad import Data.List ((\\)) import qualified Data.Map as Map -import qualified Data.Text as T import qualified Language.PureScript as P import qualified Language.PureScript.Docs as D import qualified Language.PureScript.Docs.AsMarkdown as D @@ -11,11 +10,11 @@ import qualified Language.PureScript.Docs.AsMarkdown as D main :: IO () main = do putStrLn "Test that there are no bottoms hiding in primDocsModule" - seq (T.pack (D.runDocs (D.modulesAsMarkdown [D.primDocsModule]))) (return ()) + seq (D.runDocs (D.modulesAsMarkdown [D.primDocsModule])) (return ()) putStrLn "Test that Prim is fully documented" let actualPrimTypes = map (P.runProperName . P.disqualify . fst) $ Map.toList P.primTypes - let documentedPrimTypes = map (T.pack . D.declTitle) (D.modDeclarations D.primDocsModule) + let documentedPrimTypes = map D.declTitle (D.modDeclarations D.primDocsModule) let undocumentedTypes = actualPrimTypes \\ documentedPrimTypes let extraTypes = documentedPrimTypes \\ actualPrimTypes diff --git a/tests/TestPscPublish.hs b/tests/TestPscPublish.hs index 05c082f152..14bd03742a 100644 --- a/tests/TestPscPublish.hs +++ b/tests/TestPscPublish.hs @@ -1,20 +1,12 @@ {-# OPTIONS_GHC -fno-warn-missing-signatures #-} -{-# OPTIONS_GHC -fno-warn-unused-imports #-} {-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE OverloadedStrings #-} module TestPscPublish where -import Control.Monad -import Control.Applicative -import Control.Exception -import System.Process -import System.Directory -import System.IO -import System.Exit -import qualified Data.ByteString.Lazy as BL +import System.Exit (exitFailure) import Data.ByteString.Lazy (ByteString) import qualified Data.Aeson as A -import Data.Aeson.BetterErrors import Data.Version import Language.PureScript.Docs