1{-# LANGUAGE DeriveFunctor, PatternGuards, MultiWayIf #-}
2{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
3module Idris.Docs (pprintDocs, getDocs, pprintConstDocs, FunDoc, FunDoc'(..), Docs, Docs'(..)) where
6import Idris.AbsSyntaxTree
9import Idris.Core.Evaluate
10import Idris.Docstrings (Docstring, emptyDocstring, noDocs, nullDocstring, renderDocstring, DocTerm, renderDocTerm, overview)
14import Prelude hiding ((<$>))
16import Control.Arrow (first)
20import qualified Data.Text as T
22-- TODO: Only include names with public/abstract accessibility
24-- Issue #1573 on the Issue tracker.
25-- https://github.com/idris-lang/Idris-dev/issues/1573
26data FunDoc' d = FD Name d
27 [(Name, PTerm, Plicity, Maybe d)] -- args: name, ty, implicit, docs
28 PTerm -- function type
32type FunDoc = FunDoc' (Docstring DocTerm)
34data Docs' d = FunDoc (FunDoc' d)
35 | DataDoc (FunDoc' d) -- type constructor docs
36 [FunDoc' d] -- data constructor docs
37 | ClassDoc Name d -- class docs
38 [FunDoc' d] -- method docs
39 [(Name, Maybe d)] -- parameters and their docstrings
40 [(Maybe Name, PTerm, (d, [(Name, d)]))] -- instances: name for named instances, the constraint term, the docs
42 [PTerm] -- superclasses
43 | NamedInstanceDoc Name (FunDoc' d) -- name is class
44 | ModDoc [String] -- Module name
48type Docs = Docs' (Docstring DocTerm)
51 | nullDocstring d = empty
52 | otherwise = text " -- " <>
53 renderDocstring (renderDocTerm (pprintDelab ist) (normaliseAll (tt_ctxt ist) [])) d
55pprintFD :: IState -> FunDoc -> Doc OutputAnnotation
56pprintFD ist (FD n doc args ty f)
57 = nest 4 (prettyName True (ppopt_impl ppo) [] n <+> colon <+>
58 pprintPTerm ppo [] [ n | (n@(UN n'),_,_,_) <- args
59 , not (T.isPrefixOf (T.pack "__") n') ] infixes ty <$>
60 renderDocstring (renderDocTerm (pprintDelab ist) (normaliseAll (tt_ctxt ist) [])) doc <$>
61 maybe empty (\f -> text (show f) <> line) f <>
62 let argshow = showArgs args [] in
64 then nest 4 $ text "Arguments:" <$> vsep argshow
67 where ppo = ppOptionIst ist
68 infixes = idris_infixes ist
69 showArgs ((n, ty, Exp {}, Just d):args) bnd
70 = bindingOf n False <+> colon <+>
71 pprintPTerm ppo bnd [] infixes ty <>
74 showArgs args ((n, False):bnd)
75 showArgs ((n, ty, Constraint {}, Just d):args) bnd
76 = text "Class constraint" <+>
77 pprintPTerm ppo bnd [] infixes ty <> showDoc ist d <> line
79 showArgs args ((n, True):bnd)
80 showArgs ((n, ty, Imp {}, Just d):args) bnd
81 = text "(implicit)" <+>
82 bindingOf n True <+> colon <+>
83 pprintPTerm ppo bnd [] infixes ty <>
86 showArgs args ((n, True):bnd)
87 showArgs ((n, _, _, _):args) bnd = showArgs args ((n, True):bnd)
91pprintDocs :: IState -> Docs -> Doc OutputAnnotation
92pprintDocs ist (FunDoc d) = pprintFD ist d
93pprintDocs ist (DataDoc t args)
94 = text "Data type" <+> pprintFD ist t <$>
95 if null args then text "No constructors."
96 else nest 4 (text "Constructors:" <> line <>
97 vsep (map (pprintFD ist) args))
98pprintDocs ist (ClassDoc n doc meths params instances subclasses superclasses)
99 = nest 4 (text "Type class" <+> prettyName True (ppopt_impl ppo) [] n <>
102 else line <> renderDocstring (renderDocTerm (pprintDelab ist) (normaliseAll (tt_ctxt ist) [])) doc)
104 nest 4 (text "Parameters:" <$> prettyParameters)
106 nest 4 (text "Methods:" <$>
107 vsep (map (pprintFD ist) meths))
109 nest 4 (text "Instances:" <$>
110 vsep (if null instances then [text "<no instances>"]
111 else map pprintInstance normalInstances))
113 (if null namedInstances then empty
114 else line <$> nest 4 (text "Named instances:" <$>
115 vsep (map pprintInstance namedInstances)))
117 (if null subclasses then empty
118 else line <$> nest 4 (text "Subclasses:" <$>
119 vsep (map (dumpInstance . prettifySubclasses) subclasses)))
121 (if null superclasses then empty
122 else line <$> nest 4 (text "Default superclass instances:" <$>
123 vsep (map dumpInstance superclasses)))
125 params' = zip pNames (repeat False)
127 (normalInstances, namedInstances) = partition (\(n, _, _) -> not $ isJust n)
130 pNames = map fst params
132 ppo = ppOptionIst ist
133 infixes = idris_infixes ist
135 pprintInstance (mname, term, (doc, argDocs)) =
136 nest 4 (iname mname <> dumpInstance term <>
137 (if nullDocstring doc
143 (normaliseAll (tt_ctxt ist) []))
147 else line <> vsep (map (prettyInstanceParam (map fst argDocs)) argDocs))
150 iname Nothing = empty
151 iname (Just n) = annName n <+> colon <> space
153 prettyInstanceParam params (name, doc) =
156 else prettyName True False (zip params (repeat False)) name <+>
159-- if any (isJust . snd) params
160-- then vsep (map (\(nm,md) -> prettyName True False params' nm <+> maybe empty (showDoc ist) md) params)
161-- else hsep (punctuate comma (map (prettyName True False params' . fst) params))
163 dumpInstance :: PTerm -> Doc OutputAnnotation
164 dumpInstance = pprintPTerm ppo params' [] infixes
166 prettifySubclasses (PPi (Constraint _ _) _ tm _) = prettifySubclasses tm
167 prettifySubclasses (PPi plcity nm t1 t2) = PPi plcity (safeHead nm pNames) (prettifySubclasses t1) (prettifySubclasses t2)
168 prettifySubclasses (PApp fc ref args) = PApp fc ref $ updateArgs pNames args
169 prettifySubclasses tm = tm
174 updateArgs (p:ps) ((PExp prty opts _ ref):as) = (PExp prty opts p (updateRef p ref)) : updateArgs ps as
175 updateArgs ps (a:as) = a : updateArgs ps as
178 updateRef nm (PRef fc _) = PRef fc nm
181 isSubclass (PPi (Constraint _ _) _ (PApp _ _ args) (PApp _ (PRef _ nm) args')) = nm == n && map getTm args == map getTm args'
182 isSubclass (PPi _ _ _ pt) = isSubclass pt
186 if any (isJust . snd) params
187 then vsep (map (\(nm,md) -> prettyName True False params' nm <+> maybe empty (showDoc ist) md) params)
188 else hsep (punctuate comma (map (prettyName True False params' . fst) params))
190pprintDocs ist (NamedInstanceDoc _cls doc)
191 = nest 4 (text "Named instance:" <$> pprintFD ist doc)
193pprintDocs ist (ModDoc mod docs)
194 = nest 4 $ text "Module" <+> text (concat (intersperse "." mod)) <> colon <$>
195 renderDocstring (renderDocTerm (pprintDelab ist) (normaliseAll (tt_ctxt ist) [])) docs
197-- | Determine a truncation function depending how much docs the user
200howMuch OverviewDocs = overview
202-- | Given a fully-qualified, disambiguated name, construct the
203-- documentation object for it
204getDocs :: Name -> HowMuchDocs -> Idris Docs
205getDocs n@(NS n' ns) w | n' == modDocName
207 case lookupCtxtExact n (idris_moduledocs i) of
208 Just doc -> return . ModDoc (reverse (map T.unpack ns)) $ howMuch w doc
209 Nothing -> fail $ "Module docs for " ++ show (reverse (map T.unpack ns)) ++
210 " do not exist! This shouldn't have happened and is a bug."
213 docs <- if | Just ci <- lookupCtxtExact n (idris_classes i)
215 | Just ti <- lookupCtxtExact n (idris_datatypes i)
217 | Just class_ <- classNameForInst i n
219 return $ NamedInstanceDoc class_ fd
223 return $ fmap (howMuch w) docs
224 where classNameForInst :: IState -> Name -> Maybe Name
225 classNameForInst ist n =
227 | (cn, ci) <- toAlist (idris_classes ist)
228 , n `elem` class_instances ci
231docData :: Name -> TypeInfo -> Idris Docs
233 = do tdoc <- docFun n
234 cdocs <- mapM docFun (con_names ti)
235 return (DataDoc tdoc cdocs)
237docClass :: Name -> ClassInfo -> Idris Docs
240 let docStrings = listToMaybe $ lookupCtxt n $ idris_docstrings i
241 docstr = maybe emptyDocstring fst docStrings
242 params = map (\pn -> (pn, docStrings >>= (lookup pn . snd)))
244 docsForInstance inst = fromMaybe (emptyDocstring, []) .
245 flip lookupCtxtExact (idris_docstrings i) $
247 instances = map (\inst -> (namedInst inst,
249 docsForInstance inst))
250 (nub (class_instances ci))
251 (subclasses, instances') = partition (isSubclass . (\(_,tm,_) -> tm)) instances
252 superclasses = catMaybes $ map getDInst (class_default_superclasses ci)
253 mdocs <- mapM (docFun . fst) (class_methods ci)
255 n docstr mdocs params
256 instances' (map (\(_,tm,_) -> tm) subclasses) superclasses
258 namedInst (NS n ns) = fmap (flip NS ns) (namedInst n)
259 namedInst n@(UN _) = Just n
260 namedInst _ = Nothing
262 getDInst (PInstance _ _ _ _ _ _ _ t _ _) = Just t
265 isSubclass (PPi (Constraint _ _) _ (PApp _ _ args) (PApp _ (PRef _ nm) args'))
266 = nm == n && map getTm args == map getTm args'
267 isSubclass (PPi _ _ _ pt)
272docFun :: Name -> Idris FunDoc
275 let (docstr, argDocs) = case lookupCtxt n (idris_docstrings i) of
279 let args = getPArgNames ty argDocs
280 let infixes = idris_infixes i
281 let fixdecls = filter (\(Fix _ x) -> x == funName n) infixes
282 let f = case fixdecls of
284 (Fix x _:_) -> Just x
286 return (FD n docstr args ty f)
287 where funName :: Name -> String
288 funName (UN n) = str n
289 funName (NS n _) = funName n
292getPArgNames :: PTerm -> [(Name, Docstring DocTerm)] -> [(Name, PTerm, Plicity, Maybe (Docstring DocTerm))]
293getPArgNames (PPi plicity name ty body) ds =
294 (name, ty, plicity, lookup name ds) : getPArgNames body ds
297pprintConstDocs :: IState -> Const -> String -> Doc OutputAnnotation
298pprintConstDocs ist c str = text "Primitive" <+> text (if constIsType c then "type" else "value") <+>
299 pprintPTerm (ppOptionIst ist) [] [] [] (PConstant c) <+> colon <+>
300 pprintPTerm (ppOptionIst ist) [] [] [] (t c) <>
301 nest 4 (line <> text str)
303 where t (Fl _) = PConstant $ AType ATFloat
304 t (BI _) = PConstant $ AType (ATInt ITBig)
305 t (Str _) = PConstant StrType
306 t (Ch c) = PConstant $ AType (ATInt ITChar)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list