Skip to content
This repository was archived by the owner on Aug 3, 2024. It is now read-only.

Default signatures #938

Merged
merged 8 commits into from
Sep 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 30 additions & 23 deletions haddock-api/src/Haddock/Backends/LaTeX.hs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import qualified Pretty

import GHC
import OccName
import Name ( nameOccName )
import Name ( getOccString, nameOccName, tidyNameOcc )
import RdrName ( rdrNameOcc )
import FastString ( unpackFS )
import Outputable ( panic)
Expand Down Expand Up @@ -292,7 +292,7 @@ ppDecl decl pats (doc, fnArgsDoc) instances subdocs _fxts = case unLoc decl of
-- | Just _ <- tcdTyPats d -> ppTyInst False loc doc d unicode
-- Family instances happen via FamInst now
TyClD _ d@ClassDecl{} -> ppClassDecl instances doc subdocs d unicode
SigD _ (TypeSig _ lnames ty) -> ppFunSig (doc, fnArgsDoc) (map unLoc lnames) (hsSigWcType ty) unicode
SigD _ (TypeSig _ lnames ty) -> ppFunSig Nothing (doc, fnArgsDoc) (map unLoc lnames) (hsSigWcType ty) unicode
SigD _ (PatSynSig _ lnames ty) -> ppLPatSig (doc, fnArgsDoc) (map unLoc lnames) ty unicode
ForD _ d -> ppFor (doc, fnArgsDoc) d unicode
InstD _ _ -> empty
Expand All @@ -304,7 +304,7 @@ ppDecl decl pats (doc, fnArgsDoc) instances subdocs _fxts = case unLoc decl of

ppFor :: DocForDecl DocName -> ForeignDecl DocNameI -> Bool -> LaTeX
ppFor doc (ForeignImport _ (L _ name) typ _) unicode =
ppFunSig doc [name] (hsSigType typ) unicode
ppFunSig Nothing doc [name] (hsSigType typ) unicode
ppFor _ _ _ = error "ppFor error in Haddock.Backends.LaTeX"
-- error "foreign declarations are currently not supported by --latex"

Expand Down Expand Up @@ -411,17 +411,23 @@ ppTySyn _ _ _ = error "declaration not supported by ppTySyn"
-------------------------------------------------------------------------------


ppFunSig :: DocForDecl DocName -> [DocName] -> LHsType DocNameI
-> Bool -> LaTeX
ppFunSig doc docnames (L _ typ) unicode =
ppFunSig
:: Maybe LaTeX -- ^ a prefix to put right before the signature
-> DocForDecl DocName -- ^ documentation
-> [DocName] -- ^ pattern names in the pattern signature
-> LHsType DocNameI -- ^ type of the pattern synonym
-> Bool -- ^ unicode
-> LaTeX
ppFunSig leader doc docnames (L _ typ) unicode =
ppTypeOrFunSig typ doc
( ppTypeSig names typ False
, hsep . punctuate comma $ map ppSymName names
( lead $ ppTypeSig names typ False
, lead $ hsep . punctuate comma $ map ppSymName names
, dcolon unicode
)
unicode
where
names = map getName docnames
lead = maybe id (<+>) leader

-- | Pretty-print a pattern synonym
ppLPatSig :: DocForDecl DocName -- ^ documentation
Expand All @@ -430,15 +436,7 @@ ppLPatSig :: DocForDecl DocName -- ^ documentation
-> Bool -- ^ unicode
-> LaTeX
ppLPatSig doc docnames ty unicode
= ppTypeOrFunSig typ doc
( keyword "pattern" <+> ppTypeSig names typ False
, keyword "pattern" <+> (hsep . punctuate comma $ map ppSymName names)
, dcolon unicode
)
unicode
where
typ = unLoc (hsSigType ty)
names = map getName docnames
= ppFunSig (Just (keyword "pattern")) doc docnames (hsSigType ty) unicode

-- | Pretty-print a type, adding documentation to the whole type and its
-- arguments as needed.
Expand Down Expand Up @@ -584,6 +582,7 @@ ppFds fds unicode =
hsep (map (ppDocName . unLoc) vars2)


-- TODO: associated types, associated type defaults, docs on default methods
ppClassDecl :: [DocInstance DocNameI]
-> Documentation DocName -> [(DocName, DocForDecl DocName)]
-> TyClDecl DocNameI -> Bool -> LaTeX
Expand All @@ -609,13 +608,21 @@ ppClassDecl instances doc subdocs

methodTable =
text "\\haddockpremethods{}" <> emph (text "Methods") $$
vcat [ ppFunSig doc names (hsSigWcType typ) unicode
| L _ (TypeSig _ lnames typ) <- lsigs
vcat [ ppFunSig leader doc names (hsSigType typ) unicode
| L _ (ClassOpSig _ is_def lnames typ) <- lsigs
, let doc = lookupAnySubdoc (head names) subdocs
names = map unLoc lnames ]
-- FIXME: is taking just the first name ok? Is it possible that
-- there are different subdocs for different names in a single
-- type signature?
names = map (cleanName . unLoc) lnames
leader = if is_def then Just (keyword "default") else Nothing
]
-- N.B. taking just the first name is ok. Signatures with multiple
-- names are expanded so that each name gets its own signature.

-- Get rid of the ugly '$dm' prefix on default method names
cleanName n
| isDefaultMethodOcc (occName n)
, '$':'d':'m':occStr <- getOccString n
= setName (tidyNameOcc (getName n) (mkOccName varName occStr)) n
| otherwise = n

instancesBit = ppDocInstances unicode instances

Expand Down
99 changes: 71 additions & 28 deletions haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import Data.Maybe
import Text.XHtml hiding ( name, title, p, quote )

import GHC hiding (LexicalFixity(..))
import qualified GHC
import GHC.Exts
import Name
import BooleanFormula
Expand Down Expand Up @@ -72,14 +73,14 @@ ppLFunSig :: Bool -> LinksInfo -> SrcSpan -> DocForDecl DocName ->
[Located DocName] -> LHsType DocNameI -> [(DocName, Fixity)] ->
Splice -> Unicode -> Maybe Package -> Qualification -> Html
ppLFunSig summary links loc doc lnames lty fixities splice unicode pkg qual =
ppFunSig summary links loc doc (map unLoc lnames) lty fixities
ppFunSig summary links loc noHtml doc (map unLoc lnames) lty fixities
splice unicode pkg qual

ppFunSig :: Bool -> LinksInfo -> SrcSpan -> DocForDecl DocName ->
ppFunSig :: Bool -> LinksInfo -> SrcSpan -> Html -> DocForDecl DocName ->
[DocName] -> LHsType DocNameI -> [(DocName, Fixity)] ->
Splice -> Unicode -> Maybe Package -> Qualification -> Html
ppFunSig summary links loc doc docnames typ fixities splice unicode pkg qual =
ppSigLike summary links loc mempty doc docnames fixities (unLoc typ, pp_typ)
ppFunSig summary links loc leader doc docnames typ fixities splice unicode pkg qual =
ppSigLike summary links loc leader doc docnames fixities (unLoc typ, pp_typ)
splice unicode pkg qual HideEmptyContexts
where
pp_typ = ppLType unicode qual HideEmptyContexts typ
Expand Down Expand Up @@ -226,7 +227,7 @@ ppFor :: Bool -> LinksInfo -> SrcSpan -> DocForDecl DocName
-> Splice -> Unicode -> Maybe Package -> Qualification -> Html
ppFor summary links loc doc (ForeignImport _ (L _ name) typ _) fixities
splice unicode pkg qual
= ppFunSig summary links loc doc [name] (hsSigType typ) fixities splice unicode pkg qual
= ppFunSig summary links loc noHtml doc [name] (hsSigType typ) fixities splice unicode pkg qual
ppFor _ _ _ _ _ _ _ _ _ _ = error "ppFor"


Expand Down Expand Up @@ -503,7 +504,7 @@ ppShortClassDecl summary links (ClassDecl { tcdCtxt = lctxt, tcdLName = lname, t

-- ToDo: add associated type defaults

[ ppFunSig summary links loc doc names (hsSigType typ)
[ ppFunSig summary links loc noHtml doc names (hsSigType typ)
[] splice unicode pkg qual
| L _ (ClassOpSig _ False lnames typ) <- sigs
, let doc = lookupAnySubdoc (head names) subdocs
Expand All @@ -524,8 +525,9 @@ ppClassDecl :: Bool -> LinksInfo -> [DocInstance DocNameI] -> [(DocName, Fixity)
-> [(DocName, DocForDecl DocName)] -> TyClDecl DocNameI
-> Splice -> Unicode -> Maybe Package -> Qualification -> Html
ppClassDecl summary links instances fixities loc d subdocs
decl@(ClassDecl { tcdCtxt = lctxt, tcdLName = lname, tcdTyVars = ltyvars
, tcdFDs = lfds, tcdSigs = lsigs, tcdATs = ats })
decl@(ClassDecl { tcdCtxt = lctxt, tcdLName = lname@(L _ nm)
, tcdTyVars = ltyvars, tcdFDs = lfds, tcdSigs = lsigs
, tcdATs = ats, tcdATDefs = atsDefs })
splice unicode pkg qual
| summary = ppShortClassDecl summary links decl loc subdocs splice unicode pkg qual
| otherwise = classheader +++ docSection Nothing pkg qual d
Expand All @@ -540,28 +542,68 @@ ppClassDecl summary links instances fixities loc d subdocs
-- Only the fixity relevant to the class header
fixs = ppFixities [ f | f@(n,_) <- fixities, n == unLoc lname ] qual

nm = tcdName decl

hdr = ppClassHdr summary lctxt (unLoc lname) ltyvars lfds

-- ToDo: add assocatied typ defaults
atBit = subAssociatedTypes [ ppAssocType summary links doc at subfixs splice unicode pkg qual
| at <- ats
, let n = unL . fdLName $ unL at
doc = lookupAnySubdoc (unL $ fdLName $ unL at) subdocs
subfixs = [ f | f@(n',_) <- fixities, n == n' ] ]

methodBit = subMethods [ ppFunSig summary links loc doc [name] (hsSigType typ)
subfixs splice unicode pkg qual
| L _ (ClassOpSig _ _ lnames typ) <- lsigs
, name <- map unLoc lnames
, let doc = lookupAnySubdoc name subdocs
subfixs = [ f | f@(n',_) <- fixities
, name == n' ]
]
-- N.B. taking just the first name is ok. Signatures with multiple names
-- are expanded so that each name gets its own signature.
-- Associated types
atBit = subAssociatedTypes
[ ppAssocType summary links doc at subfixs splice unicode pkg qual
<+>
subDefaults (maybeToList defTys)
| at <- ats
, let name = unL . fdLName $ unL at
doc = lookupAnySubdoc name subdocs
subfixs = filter ((== name) . fst) fixities
defTys = ppDefaultAssocTy name <$> lookupDAT name
]

-- Default associated types
ppDefaultAssocTy n (vs,t,d') = ppTySyn summary links [] loc d' synDecl
splice unicode pkg qual
where
synDecl = SynDecl { tcdSExt = noExt
, tcdLName = noLoc n
, tcdTyVars = vs
, tcdFixity = GHC.Prefix
, tcdRhs = t }

lookupDAT name = Map.lookup (getName name) defaultAssocTys
defaultAssocTys = Map.fromList
[ (getName name, (vs, typ, doc))
| L _ (FamEqn { feqn_rhs = typ
, feqn_tycon = L _ name
, feqn_pats = vs }) <- atsDefs
, let doc = noDocForDecl -- TODO: get docs for associated type defaults
]

-- Methods
methodBit = subMethods
[ ppFunSig summary links loc noHtml doc [name] (hsSigType typ)
subfixs splice unicode pkg qual
<+>
subDefaults (maybeToList defSigs)
| ClassOpSig _ False lnames typ <- sigs
, name <- map unLoc lnames
, let doc = lookupAnySubdoc name subdocs
subfixs = filter ((== name) . fst) fixities
defSigs = ppDefaultFunSig name <$> lookupDM name
]
-- N.B. taking just the first name is ok. Signatures with multiple names
-- are expanded so that each name gets its own signature.

-- Default methods
ppDefaultFunSig n (t, d') = ppFunSig summary links loc (keyword "default")
d' [n] (hsSigType t) [] splice unicode pkg qual

lookupDM name = Map.lookup (getOccString name) defaultMethods
defaultMethods = Map.fromList
[ (nameStr, (typ, doc))
| ClassOpSig _ True lnames typ <- sigs
, name <- map unLoc lnames
, let doc = lookupAnySubdoc name subdocs
, '$':'d':'m':nameStr <- [getOccString name]
]

-- Minimal complete definition
minimalBit = case [ s | MinimalSig _ _ (L _ s) <- sigs ] of
-- Miminal complete definition = every shown method
And xs : _ | sort [getName n | L _ (Var (L _ n)) <- xs] ==
Expand All @@ -570,7 +612,7 @@ ppClassDecl summary links instances fixities loc d subdocs

-- Minimal complete definition = the only shown method
Var (L _ n) : _ | [getName n] ==
[getName n' | L _ (ClassOpSig _ _ ns _) <- lsigs, L _ n' <- ns]
[getName n' | ClassOpSig _ _ ns _ <- sigs, L _ n' <- ns]
-> noHtml

-- Minimal complete definition = nothing
Expand All @@ -585,6 +627,7 @@ ppClassDecl summary links instances fixities loc d subdocs
where wrap | p = parens | otherwise = id
ppMinimal p (Parens x) = ppMinimal p (unLoc x)

-- Instances
instancesBit = ppInstances links (OriginClass nm) instances
splice unicode pkg qual

Expand Down
4 changes: 4 additions & 0 deletions haddock-api/src/Haddock/Backends/Xhtml/Layout.hs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ module Haddock.Backends.Xhtml.Layout (
subInstances, subOrphanInstances,
subInstHead, subInstDetails, subFamInstDetails,
subMethods,
subDefaults,
subMinimal,

topDeclElem, declElem,
Expand Down Expand Up @@ -256,6 +257,9 @@ instAnchorId iid = makeAnchorId $ "i:" ++ iid
subMethods :: [Html] -> Html
subMethods = divSubDecls "methods" "Methods" . subBlock

subDefaults :: [Html] -> Html
subDefaults = divSubDecls "default" "" . subBlock

subMinimal :: Html -> Html
subMinimal = divSubDecls "minimal" "Minimal complete definition" . Just . declElem

Expand Down
20 changes: 12 additions & 8 deletions haddock-api/src/Haddock/Convert.hs
Original file line number Diff line number Diff line change
Expand Up @@ -95,19 +95,20 @@ tyThingToLHsDecl t = case t of

atTyClDecls = map extractAtItem (classATItems cl)
(atFamDecls, atDefFamDecls) = unzip (rights atTyClDecls)
vs = tyConVisibleTyVars (classTyCon cl)

in withErrs (lefts atTyClDecls) . TyClD noExt $ ClassDecl
{ tcdCtxt = synifyCtx (classSCTheta cl)
, tcdLName = synifyName cl
, tcdTyVars = synifyTyVars (tyConVisibleTyVars (classTyCon cl))
, tcdTyVars = synifyTyVars vs
, tcdFixity = Prefix
, tcdFDs = map (\ (l,r) -> noLoc
(map (noLoc . getName) l, map (noLoc . getName) r) ) $
snd $ classTvsFds cl
, tcdSigs = noLoc (MinimalSig noExt NoSourceText . noLoc . fmap noLoc $ classMinimalDef cl) :
[ noLoc tcdSig
| clsOp <- classOpItems cl
, tcdSig <- synifyTcIdSig DeleteTopLevelQuantification clsOp ]
, tcdSig <- synifyTcIdSig vs clsOp ]
, tcdMeths = emptyBag --ignore default method definitions, they don't affect signature
-- class associated-types are a subset of TyCon:
, tcdATs = atFamDecls
Expand Down Expand Up @@ -387,11 +388,14 @@ synifyIdSig s vs i = TypeSig noExt [synifyName i] (synifySigWcType s vs (varType
-- | Turn a 'ClassOpItem' into a list of signatures. The list returned is going
-- to contain the synified 'ClassOpSig' as well (when appropriate) a default
-- 'ClassOpSig'.
synifyTcIdSig :: SynifyTypeState -> ClassOpItem -> [Sig GhcRn]
synifyTcIdSig s (i, dm) =
[ ClassOpSig noExt False [synifyName i] (synifySigType s (varType i)) ] ++
[ ClassOpSig noExt True [noLoc dn] (synifySigType s dt)
synifyTcIdSig :: [TyVar] -> ClassOpItem -> [Sig GhcRn]
synifyTcIdSig vs (i, dm) =
[ ClassOpSig noExt False [synifyName i] (mainSig (varType i)) ] ++
[ ClassOpSig noExt True [noLoc dn] (defSig dt)
| Just (dn, GenericDM dt) <- [dm] ]
where
mainSig t = synifySigType DeleteTopLevelQuantification vs t
defSig t = synifySigType ImplicitizeForAll vs t

synifyCtx :: [PredType] -> LHsContext GhcRn
synifyCtx = noLoc . map (synifyType WithinType [])
Expand Down Expand Up @@ -461,10 +465,10 @@ data SynifyTypeState
-- the defining class gets to quantify all its functions for free!


synifySigType :: SynifyTypeState -> Type -> LHsSigType GhcRn
synifySigType :: SynifyTypeState -> [TyVar] -> Type -> LHsSigType GhcRn
-- The empty binders is a bit suspicious;
-- what if the type has free variables?
synifySigType s ty = mkEmptyImplicitBndrs (synifyType s [] ty)
synifySigType s vs ty = mkEmptyImplicitBndrs (synifyType s vs ty)

synifySigWcType :: SynifyTypeState -> [TyVar] -> Type -> LHsSigWcType GhcRn
-- Ditto (see synifySigType)
Expand Down
3 changes: 3 additions & 0 deletions haddock-api/src/Haddock/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,9 @@ instance SetName DocName where
setName name' (Undocumented _) = Undocumented name'


instance HasOccName DocName where

occName = occName . getName

-----------------------------------------------------------------------------
-- * Instances
Expand Down
13 changes: 10 additions & 3 deletions haddock-api/src/Haddock/Utils.hs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE ViewPatterns #-}
-----------------------------------------------------------------------------
-- |
-- Module : Haddock.Utils
Expand Down Expand Up @@ -165,8 +166,8 @@ restrictTo names (L loc decl) = L loc $ case decl of
TyClD x d | isDataDecl d ->
TyClD x (d { tcdDataDefn = restrictDataDefn names (tcdDataDefn d) })
TyClD x d | isClassDecl d ->
TyClD x (d { tcdSigs = restrictDecls names (tcdSigs d),
tcdATs = restrictATs names (tcdATs d) })
TyClD x (d { tcdSigs = restrictDecls names (tcdSigs d)
, tcdATs = restrictATs names (tcdATs d) })
_ -> decl

restrictDataDefn :: [Name] -> HsDataDefn GhcRn -> HsDataDefn GhcRn
Expand Down Expand Up @@ -204,7 +205,13 @@ restrictCons names decls = [ L p d | L p (Just d) <- map (fmap keep) decls ]
keep _ = Nothing

restrictDecls :: [Name] -> [LSig GhcRn] -> [LSig GhcRn]
restrictDecls names = mapMaybe (filterLSigNames (`elem` names))
restrictDecls names = mapMaybe (filterLSigNames func)
where func n | n `elem` names = True

-- let through default method iff method is let through
| '$':'d':'m':strN <- getOccString n
, strN `elem` map getOccString names = True
| otherwise = False


restrictATs :: [Name] -> [LFamilyDecl GhcRn] -> [LFamilyDecl GhcRn]
Expand Down
Loading