packages feed

haskell-gi 0.20.3 → 0.21.0

raw patch · 24 files changed

+520/−328 lines, 24 filesdep +semigroupsdep ~haskell-gi-basePVP ok

version bump matches the API change (PVP)

Dependencies added: semigroups

Dependency ranges changed: haskell-gi-base

API changes (from Hackage documentation)

- Data.GI.CodeGen.Code: exportMethod :: HaddockSection -> SymbolName -> CodeGen ()
- Data.GI.CodeGen.Code: exportProperty :: HaddockSection -> SymbolName -> CodeGen ()
- Data.GI.CodeGen.Code: exportSignal :: HaddockSection -> SymbolName -> CodeGen ()
- Data.GI.CodeGen.Code: exportToplevel :: SymbolName -> CodeGen ()
- Data.GI.CodeGen.Haddock: addModuleDocumentation :: Documentation -> CodeGen ()
+ Data.GI.CodeGen.API: [cbDocumentation] :: Callback -> Documentation
+ Data.GI.CodeGen.API: [fieldDocumentation] :: Field -> Documentation
+ Data.GI.CodeGen.API: [propDoc] :: Property -> Documentation
+ Data.GI.CodeGen.API: [sigDoc] :: Signal -> Documentation
+ Data.GI.CodeGen.Code: EnumSection :: NamedSection
+ Data.GI.CodeGen.Code: FlagSection :: NamedSection
+ Data.GI.CodeGen.Code: MethodSection :: NamedSection
+ Data.GI.CodeGen.Code: NamedSubsection :: NamedSection -> Text -> HaddockSection
+ Data.GI.CodeGen.Code: PropertySection :: NamedSection
+ Data.GI.CodeGen.Code: SignalSection :: NamedSection
+ Data.GI.CodeGen.Code: ToplevelSection :: HaddockSection
+ Data.GI.CodeGen.Code: addSectionFormattedDocs :: HaddockSection -> Text -> CodeGen ()
+ Data.GI.CodeGen.Code: data HaddockSection
+ Data.GI.CodeGen.Code: data NamedSection
+ Data.GI.CodeGen.Code: export :: HaddockSection -> SymbolName -> CodeGen ()
+ Data.GI.CodeGen.Code: instance Data.Semigroup.Semigroup Data.GI.CodeGen.Code.Code
+ Data.GI.CodeGen.Code: instance GHC.Classes.Eq Data.GI.CodeGen.Code.HaddockSection
+ Data.GI.CodeGen.Code: instance GHC.Classes.Eq Data.GI.CodeGen.Code.NamedSection
+ Data.GI.CodeGen.Code: instance GHC.Classes.Ord Data.GI.CodeGen.Code.HaddockSection
+ Data.GI.CodeGen.Code: instance GHC.Classes.Ord Data.GI.CodeGen.Code.NamedSection
+ Data.GI.CodeGen.Code: instance GHC.Show.Show Data.GI.CodeGen.Code.HaddockSection
+ Data.GI.CodeGen.Code: instance GHC.Show.Show Data.GI.CodeGen.Code.NamedSection
+ Data.GI.CodeGen.Haddock: addSectionDocumentation :: HaddockSection -> Documentation -> CodeGen ()
+ Data.GI.CodeGen.ModulePath: instance Data.Semigroup.Semigroup Data.GI.CodeGen.ModulePath.ModulePath
+ Data.GI.CodeGen.Overrides: instance Data.Semigroup.Semigroup Data.GI.CodeGen.Overrides.Overrides
+ Data.GI.GIR.Callback: [cbDocumentation] :: Callback -> Documentation
+ Data.GI.GIR.Field: [fieldDocumentation] :: Field -> Documentation
+ Data.GI.GIR.Property: [propDoc] :: Property -> Documentation
+ Data.GI.GIR.Signal: [sigDoc] :: Signal -> Documentation
- Data.GI.CodeGen.API: Callback :: Callable -> Maybe Text -> Callback
+ Data.GI.CodeGen.API: Callback :: Callable -> Maybe Text -> Documentation -> Callback
- Data.GI.CodeGen.API: Field :: Text -> Bool -> Type -> Maybe Bool -> Maybe Callback -> Int -> [FieldInfoFlag] -> Maybe DeprecationInfo -> Field
+ Data.GI.CodeGen.API: Field :: Text -> Bool -> Type -> Maybe Bool -> Maybe Callback -> Int -> [FieldInfoFlag] -> Documentation -> Maybe DeprecationInfo -> Field
- Data.GI.CodeGen.API: Property :: Text -> Type -> [PropertyFlag] -> Maybe Bool -> Maybe Bool -> Transfer -> Maybe DeprecationInfo -> Property
+ Data.GI.CodeGen.API: Property :: Text -> Type -> [PropertyFlag] -> Maybe Bool -> Maybe Bool -> Transfer -> Documentation -> Maybe DeprecationInfo -> Property
- Data.GI.CodeGen.API: Signal :: Text -> Callable -> Maybe DeprecationInfo -> Signal
+ Data.GI.CodeGen.API: Signal :: Text -> Callable -> Maybe DeprecationInfo -> Documentation -> Signal
- Data.GI.GIR.Callback: Callback :: Callable -> Maybe Text -> Callback
+ Data.GI.GIR.Callback: Callback :: Callable -> Maybe Text -> Documentation -> Callback
- Data.GI.GIR.Field: Field :: Text -> Bool -> Type -> Maybe Bool -> Maybe Callback -> Int -> [FieldInfoFlag] -> Maybe DeprecationInfo -> Field
+ Data.GI.GIR.Field: Field :: Text -> Bool -> Type -> Maybe Bool -> Maybe Callback -> Int -> [FieldInfoFlag] -> Documentation -> Maybe DeprecationInfo -> Field
- Data.GI.GIR.Property: Property :: Text -> Type -> [PropertyFlag] -> Maybe Bool -> Maybe Bool -> Transfer -> Maybe DeprecationInfo -> Property
+ Data.GI.GIR.Property: Property :: Text -> Type -> [PropertyFlag] -> Maybe Bool -> Maybe Bool -> Transfer -> Documentation -> Maybe DeprecationInfo -> Property
- Data.GI.GIR.Signal: Signal :: Text -> Callable -> Maybe DeprecationInfo -> Signal
+ Data.GI.GIR.Signal: Signal :: Text -> Callable -> Maybe DeprecationInfo -> Documentation -> Signal

Files

ChangeLog.md view
@@ -1,3 +1,9 @@+### 0.20.4+++ Improve marshaling of array arguments with no specified size. This improves the generated bindings for various functions, for instance [`GObject.signalEmitv`](https://hackage.haskell.org/package/gi-gobject/docs/GI-GObject-Functions.html#v:signalEmitv).+++ Replace the enable-overloading flags with a explicit CPP check of the version of `haskell-gi-overloading` we are being compiled against, see [issue 124](https://github.com/haskell-gi/haskell-gi/issues/124) for the rationale.+ ### 0.20.3  + Make the overloading code protected by a CPP conditional, depending on ENABLE_OVERLOADING being defined. See [issue 107](https://github.com/haskell-gi/haskell-gi/issues/107).
haskell-gi.cabal view
@@ -1,5 +1,5 @@ name:                haskell-gi-version:             0.20.3+version:             0.21.0 synopsis:            Generate Haskell bindings for GObject Introspection capable libraries description:         Generate Haskell bindings for GObject Introspection capable libraries. This includes most notably                      Gtk+, but many other libraries in the GObject ecosystem provide introspection data too.@@ -26,7 +26,7 @@ Library   pkgconfig-depends:   gobject-introspection-1.0 >= 1.32, gobject-2.0 >= 2.32   build-depends:       base >= 4.7 && < 5,-                       haskell-gi-base == 0.20.*,+                       haskell-gi-base == 0.21.*,                        Cabal >= 1.20,                        attoparsec == 0.13.*,                        containers,@@ -42,6 +42,9 @@                        xml-conduit >= 1.3.0,                        regex-tdfa >= 1.2,                        text >= 1.0++  if !impl(ghc >= 8.0)+    build-depends: semigroups == 0.18.*    extensions:          CPP, ForeignFunctionInterface, DoAndIfThenElse, LambdaCase, RankNTypes, OverloadedStrings   ghc-options:         -Wall -fno-warn-missing-signatures -fwarn-incomplete-patterns -fno-warn-name-shadowing
lib/Data/GI/CodeGen/CabalHooks.hs view
@@ -9,12 +9,6 @@ import Distribution.Simple.Setup import Distribution.Simple (UserHooks(..), simpleUserHooks,                             defaultMainWithHooks, OptimisationLevel(..))-#if !MIN_VERSION_Cabal(2,0,0)-import Distribution.Simple (Dependency(..), PackageName(..), unPackageName)-#else-import Distribution.Types.PkgconfigDependency (PkgconfigDependency(..))-import Distribution.Types.PkgconfigName (unPkgconfigName)-#endif import Distribution.PackageDescription  import Data.GI.CodeGen.API (loadGIRInfo)@@ -25,14 +19,12 @@ import Data.GI.CodeGen.ModulePath (toModulePath) import Data.GI.CodeGen.Overrides (parseOverridesFile, girFixups,                                   filterAPIsAndDeps)-import Data.GI.CodeGen.PkgConfig (tryPkgConfig)-import Data.GI.CodeGen.Util (ucFirst, tshow, utf8ReadFile, utf8WriteFile)+import Data.GI.CodeGen.Util (ucFirst, utf8ReadFile)  import Control.Monad (when, void)  import Data.Maybe (fromJust, fromMaybe) import qualified Data.Map as M-import Data.Monoid ((<>)) import Data.Text (Text) import qualified Data.Text as T @@ -42,43 +34,6 @@ type ConfHook = (GenericPackageDescription, HookedBuildInfo) -> ConfigFlags               -> IO LocalBuildInfo -#if !MIN_VERSION_Cabal(2,0,0)-#define PkgconfigDependency Dependency--unPkgconfigName :: PackageName -> String-unPkgconfigName = unPackageName--unFlagName :: FlagName -> String-unFlagName (FlagName n) = n-#endif---- | Generate the @PkgInfo@ module, listing the build information for--- the module. We include in particular the versions for the--- `pkg-config` dependencies of the module.-genPkgInfo :: [PkgconfigDependency] -> [(FlagName, Bool)] -> FilePath -> Text-           -> IO ()-genPkgInfo deps flags fName modName = do-  versions <- mapM findVersion deps-  utf8WriteFile fName $ T.unlines-         [ "module " <> modName <> " (pkgConfigVersions, flags) where"-         , ""-         , "import Prelude (String, Bool(..))"-         , ""-         , "pkgConfigVersions :: [(String, String)]"-         , "pkgConfigVersions = " <> tshow versions-         , ""-         , "flags :: [(String, Bool)]"-         , "flags = " <> tshow flags'-         ]-    where findVersion :: PkgconfigDependency -> IO (Text, Text)-          findVersion (PkgconfigDependency n _) =-              tryPkgConfig (T.pack (unPkgconfigName n)) >>= \case-                  Just v -> return v-                  Nothing -> error ("Could not determine version for required pkg-config module \"" <> (unPkgconfigName n) <> "\".")--          flags' :: [(String, Bool)]-          flags' = map (\(f, v) -> (unFlagName f, v)) flags- -- | A convenience helper for `confHook`, such that bindings for the -- given module are generated in the @configure@ step of @cabal@. confCodeGenHook :: Text -- ^ name@@ -109,8 +64,7 @@    let m = genCode cfg allAPIs (toModulePath name) (genModule apis) -  let pkgInfoMod = "GI." <> ucFirst name <> ".PkgInfo"-      em' = map (MN.fromString . T.unpack) (pkgInfoMod : listModuleTree m)+  let em' = map (MN.fromString . T.unpack) (listModuleTree m)       ctd' = ((condTreeData . fromJust . condLibrary) gpd) {exposedModules = em'}       cL' = ((fromJust . condLibrary) gpd) {condTreeData = ctd'}       gpd' = gpd {condLibrary = Just cL'}@@ -119,12 +73,6 @@                                 </> "GI" </> T.unpack (ucFirst name) <.> "hs")   when (not alreadyDone) $ do     void $ writeModuleTree verbosity outputDir m-    genPkgInfo ((pkgconfigDepends . libBuildInfo . condTreeData .-                  fromJust . condLibrary) gpd)-               (configConfigurationsFlags flags)-               (fromMaybe "" outputDir-                   </> "GI" </> T.unpack (ucFirst name) </> "PkgInfo.hs")-               pkgInfoMod    lbi <- defaultConfHook (gpd', hbi) flags 
lib/Data/GI/CodeGen/Callable.hs view
@@ -36,7 +36,7 @@ import Data.GI.CodeGen.API import Data.GI.CodeGen.Code import Data.GI.CodeGen.Conversions-import Data.GI.CodeGen.Haddock (deprecatedPragma,+import Data.GI.CodeGen.Haddock (deprecatedPragma, writeHaddock,                                 writeDocumentation, RelativeDocPosition(..),                                 writeArgDocumentation, writeReturnDocumentation) import Data.GI.CodeGen.SymbolNaming@@ -85,7 +85,9 @@         line =<< last     return hSymbol     where-    hSymbol = cSymbol+    hSymbol = if T.any (== '_') cSymbol+              then lcFirst cSymbol+              else "_" <> cSymbol     first = "foreign import ccall \"" <> cSymbol <> "\" " <> hSymbol <> " :: "     fArgStr arg = do         ft <- foreignType $ argType arg@@ -252,7 +254,8 @@           Just name -> freeFn arg name $                        -- Pass in the length argument in case it's needed.                        case argType arg of-                         TCArray False (-1) (-1) _ -> undefined+                         TCArray False (-1) (-1) _ ->+                           parenthesize ("length " <> escapedArgName arg)                          TCArray False (-1) length _ ->                              escapedArgName $ (args callable)!!length                          _ -> undefined@@ -654,9 +657,12 @@     where       unwrappedConvertResult rname =           case returnType callable of-            -- Arrays without length information are just passed-            -- along.-            Just (TCArray False (-1) (-1) _) -> return rname+            -- Arrays without length information cannot be converted+            -- into Haskell values.+            Just (t@(TCArray False (-1) (-1) _)) ->+                badIntroError ("`" <> tshow t <>+                "' is an array type, but contains no length information,\n"+                <> "so it cannot be unpacked.")             -- Not zero-terminated C arrays require knowledge of the             -- length, so we deal with them directly.             Just (t@(TCArray False _ _ _)) ->@@ -677,11 +683,12 @@       Just name' -> return name'       Nothing -> badIntroError $ "Parameter " <> name <> " not found!"   case argType arg of-      -- Passed along as a raw pointer-      TCArray False (-1) (-1) _ ->+      t@(TCArray False (-1) (-1) _) ->           if argCallerAllocates arg           then return inName-          else genConversion inName $ apply $ M "peek"+          else  badIntroError ("`" <> tshow t <>+                "' is an array type, but contains no length information,\n"+                <> "so it cannot be unpacked.")       t@(TCArray False _ _ _) -> do           aname' <- if argCallerAllocates arg                     then return inName@@ -925,6 +932,12 @@    blank +  writeHaddock DocBeforeSymbol dynamicDoc+   let dyn = DynamicWrapper { dynamicWrapper = wrapper                            , dynamicType    = typeSynonym }   genHaskellWrapper n (DynamicForeignSymbol dyn) callable' WithClosures++  where+    dynamicDoc :: Text+    dynamicDoc = "Given a pointer to a foreign C function, wrap it into a function callable from Haskell."
lib/Data/GI/CodeGen/Code.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} module Data.GI.CodeGen.Code     ( Code-    , ModuleInfo(moduleCode, moduleDoc)+    , ModuleInfo(moduleCode, sectionDocs)     , ModuleFlag(..)     , BaseCodeGen     , CodeGen@@ -44,13 +44,14 @@     , setModuleFlags     , setModuleMinBase -    , exportToplevel     , exportModule     , exportDecl-    , exportMethod-    , exportProperty-    , exportSignal+    , export+    , HaddockSection(..)+    , NamedSection(..) +    , addSectionFormattedDocs+     , findAPI     , getAPI     , findAPIByName@@ -74,6 +75,7 @@ import qualified Data.Map.Strict as M import Data.Sequence (ViewL ((:<)), viewl, (|>)) import qualified Data.Sequence as Seq+import qualified Data.Semigroup as Sem import qualified Data.Set as Set import Data.Text (Text) import qualified Data.Text as T@@ -94,12 +96,12 @@ import Data.GI.CodeGen.ProjectInfo (authors, license, maintainers)  -- | Set of CPP conditionals understood by the code generator.-data CPPConditional = CPPIfdef Text -- ^ #ifdef Foo+data CPPConditional = CPPIf Text -- ^ #if Foo   deriving (Eq, Show, Ord)  -- | The generated `Code` is a sequence of `CodeToken`s. newtype Code = Code (Seq.Seq CodeToken)-  deriving (Monoid, Eq, Show, Ord)+  deriving (Sem.Semigroup, Monoid, Eq, Show, Ord)  -- | Initializes a code block to the empty sequence. emptyCode :: Code@@ -127,9 +129,20 @@ type Deps = Set.Set Text  -- | Subsection of the haddock documentation where the export should--- be located.-type HaddockSection = Text+-- be located, or alternatively the toplevel section.+data HaddockSection = ToplevelSection+                    | NamedSubsection NamedSection Text+  deriving (Show, Eq, Ord) +-- | Known subsections. The ordering here is the ordering in which+-- they will appear in the haddocks.+data NamedSection = MethodSection+                  | PropertySection+                  | SignalSection+                  | EnumSection+                  | FlagSection+  deriving (Show, Eq, Ord)+ -- | Symbol to export. type SymbolName = Text @@ -145,11 +158,9 @@     } deriving (Show, Eq, Ord)  -- | Possible types of exports.-data ExportType = ExportTypeDecl -- ^ A type declaration.-                | ExportToplevel -- ^ An export in no specific section.-                | ExportMethod HaddockSection -- ^ A method for a struct/union, etc.-                | ExportProperty HaddockSection -- ^ A property for an object/interface.-                | ExportSignal HaddockSection  -- ^ A signal for an object/interface.+data ExportType = ExportSymbol HaddockSection -- ^ An export in the+                  -- given haddock section.+                | ExportTypeDecl -- ^ A type declaration.                 | ExportModule   -- ^ Reexport of a whole module.                   deriving (Show, Eq, Ord) @@ -166,7 +177,9 @@     , modulePragmas :: Set.Set Text -- ^ Set of language pragmas for the module.     , moduleGHCOpts :: Set.Set Text -- ^ GHC options for compiling the module.     , moduleFlags   :: Set.Set ModuleFlag -- ^ Flags for the module.-    , moduleDoc     :: Maybe Text -- ^ Documentation for the module.+    , sectionDocs   :: M.Map HaddockSection Text -- ^ Documentation+                                     -- for the different sections in+                                     -- the module.     , moduleMinBase :: BaseVersion -- ^ Minimal version of base the                                    -- module will work on.     }@@ -198,7 +211,7 @@                            , modulePragmas = Set.empty                            , moduleGHCOpts = Set.empty                            , moduleFlags = Set.empty-                           , moduleDoc = Nothing+                           , sectionDocs = M.empty                            , moduleMinBase = Base47                            } @@ -258,7 +271,7 @@ cleanInfo info = info { moduleCode = emptyCode, submodules = M.empty,                         bootCode = emptyCode, moduleExports = Seq.empty,                         qualifiedImports = Set.empty,-                        moduleDoc = Nothing, moduleMinBase = Base47 }+                        sectionDocs = M.empty, moduleMinBase = Base47 }  -- | Run the given code generator using the state and config of an -- ambient CodeGen, but without adding the generated code to@@ -305,13 +318,13 @@         newGHCOpts = Set.union (moduleGHCOpts oldState) (moduleGHCOpts newState)         newFlags = Set.union (moduleFlags oldState) (moduleFlags newState)         newBoot = bootCode oldState <> bootCode newState-        newDoc = moduleDoc oldState <> moduleDoc newState+        newDocs = sectionDocs oldState <> sectionDocs newState         newMinBase = max (moduleMinBase oldState) (moduleMinBase newState)     in oldState {moduleDeps = newDeps, submodules = newSubmodules,                  moduleExports = newExports, qualifiedImports = newImports,                  modulePragmas = newPragmas,                  moduleGHCOpts = newGHCOpts, moduleFlags = newFlags,-                 bootCode = newBoot, moduleDoc = newDoc,+                 bootCode = newBoot, sectionDocs = newDocs,                  moduleMinBase = newMinBase }  -- | Merge the infos, including code too.@@ -541,15 +554,15 @@   blank   return x --- | Guard a block of code with @#ifdef@.-cppIfdef :: Text -> BaseCodeGen e a -> BaseCodeGen e a-cppIfdef cond cg = do+-- | Guard a block of code with @#if@.+cppIfBlock :: Text -> BaseCodeGen e a -> BaseCodeGen e a+cppIfBlock cond cg = do   (x, code) <- recurseWithState addConditional cg-  tellCode (CPPBlock (CPPIfdef cond) code)+  tellCode (CPPBlock (CPPIf cond) code)   blank   return x     where addConditional :: CGState -> CGState-          addConditional cgs = CGState {cgsCPPConditionals = CPPIfdef cond :+          addConditional cgs = CGState {cgsCPPConditionals = CPPIf cond :                                          cgsCPPConditionals cgs}  -- | Possible features to test via CPP.@@ -558,7 +571,7 @@ -- | Guard a code block with CPP code, such that it is included only -- if the specified feature is enabled. cppIf :: CPPGuard -> BaseCodeGen e a -> BaseCodeGen e a-cppIf CPPOverloading = cppIfdef "ENABLE_OVERLOADING"+cppIf CPPOverloading = cppIfBlock "ENABLE_OVERLOADING"  -- | Write the given code into the .hs-boot file for the current module. hsBoot :: BaseCodeGen e a -> BaseCodeGen e a@@ -572,35 +585,23 @@         addGuards (cond : conds) c = codeSingleton $ CPPBlock cond (addGuards conds c)  -- | Add a export to the current module.-export :: ([CPPConditional] -> Export) -> CodeGen ()-export partial =+exportPartial :: ([CPPConditional] -> Export) -> CodeGen ()+exportPartial partial =     modify' $ \(cgs, s) -> (cgs,                             let e = partial $ cgsCPPConditionals cgs                             in s{moduleExports = moduleExports s |> e})  -- | Reexport a whole module. exportModule :: SymbolName -> CodeGen ()-exportModule m = export (Export ExportModule m)---- | Export a toplevel (i.e. belonging to no section) symbol.-exportToplevel :: SymbolName -> CodeGen ()-exportToplevel t = export (Export ExportToplevel t)+exportModule m = exportPartial (Export ExportModule m)  -- | Add a type declaration-related export. exportDecl :: SymbolName -> CodeGen ()-exportDecl d = export (Export ExportTypeDecl d)---- | Add a method export under the given section.-exportMethod :: HaddockSection -> SymbolName -> CodeGen ()-exportMethod s n = export (Export (ExportMethod s) n)---- | Add a property-related export under the given section.-exportProperty :: HaddockSection -> SymbolName -> CodeGen ()-exportProperty s n = export (Export (ExportProperty s) n)+exportDecl d = exportPartial (Export ExportTypeDecl d) --- | Add a signal-related export under the given section.-exportSignal :: HaddockSection -> SymbolName -> CodeGen ()-exportSignal s n = export (Export (ExportSignal s) n)+-- | Export a symbol in the given haddock subsection.+export :: HaddockSection -> SymbolName -> CodeGen ()+export s n = exportPartial (Export (ExportSymbol s) n)  -- | Set the language pragmas for the current module. setLanguagePragmas :: [Text] -> CodeGen ()@@ -622,9 +623,15 @@ setModuleMinBase v =     modify' $ \(cgs, s) -> (cgs, s{moduleMinBase = max v (moduleMinBase s)}) +-- | Add documentation for a given section.+addSectionFormattedDocs :: HaddockSection -> Text -> CodeGen ()+addSectionFormattedDocs section docs =+    modify' $ \(cgs, s) -> (cgs, s{sectionDocs = M.insertWith (<>) section+                                                 docs (sectionDocs s)})+ -- | Format a CPP conditional. cppCondFormat :: CPPConditional -> (Text, Text)-cppCondFormat (CPPIfdef c) = ("#ifdef " <> c <> "\n", "#endif\n")+cppCondFormat (CPPIf c) = ("#if " <> c <> "\n", "#endif\n")  -- | Return a text representation of the `Code`. codeToText :: Code -> Text@@ -672,7 +679,7 @@ formatToplevel [] = Nothing formatToplevel exports =     Just . T.concat . map (formatExport exportSymbol)-         . filter ((== ExportToplevel) . exportType) $ exports+         . filter ((== ExportSymbol ToplevelSection) . exportType) $ exports  -- | Format the type declarations section. formatTypeDecls :: [Export] -> Maybe Text@@ -687,30 +694,44 @@ -- | A subsection name, with an optional anchor name. data Subsection = Subsection { subsectionTitle  :: Text                              , subsectionAnchor :: Maybe Text+                             , subsectionDoc    :: Maybe Text                              } deriving (Eq, Show, Ord) --- | A subsection with an anchor given by the title and @prefix:title@ anchor.-subsecWithPrefix prefix title =+-- | A subsection with an anchor given by the title and @prefix:title@+-- anchor, and the given documentation.+subsecWithPrefix :: NamedSection -> Text -> Maybe Text -> Subsection+subsecWithPrefix mainSection title doc =   Subsection { subsectionTitle = title-             , subsectionAnchor = Just (prefix <> ":" <> title) }+             , subsectionAnchor = Just (prefix <> ":" <> title)+             , subsectionDoc = doc }+  where prefix = case mainSection of+          MethodSection -> "method"+          PropertySection -> "attr"+          SignalSection -> "signal"+          EnumSection -> "enum"+          FlagSection -> "flag" +-- | User-facing name in the Haddocks for the given main section.+mainSectionName :: NamedSection -> Text+mainSectionName MethodSection = "Methods"+mainSectionName PropertySection = "Properties"+mainSectionName SignalSection = "Signals"+mainSectionName EnumSection = "Enumerations"+mainSectionName FlagSection = "Flags"+ -- | Format a given section made of subsections.-formatSection :: Text -> (Export -> Maybe (Subsection, Export)) ->-                 [Export] -> Maybe Text-formatSection section filter exports =-    if M.null exportedSubsections+formatSection :: NamedSection -> [(Subsection, Export)] -> Maybe Text+formatSection section exports =+    if null exports     then Nothing-    else Just . T.unlines $ [" -- * " <> section+    else Just . T.unlines $ [" -- * " <> mainSectionName section                             , ( T.unlines                               . map formatSubsection                               . M.toList ) exportedSubsections]      where-      filteredExports :: [(Subsection, Export)]-      filteredExports = catMaybes (map filter exports)-       exportedSubsections :: M.Map Subsection (Set.Set Export)-      exportedSubsections = foldr extract M.empty filteredExports+      exportedSubsections = foldr extract M.empty exports        extract :: (Subsection, Export) -> M.Map Subsection (Set.Set Export)               -> M.Map Subsection (Set.Set Export)@@ -723,44 +744,37 @@                                     Just anchor -> subsectionTitle subsec <>                                                    " #" <> anchor <> "#"                                     Nothing -> subsectionTitle subsec+                    , case subsectionDoc subsec of+                        Just text -> "{- | " <> text  <> "\n-}"+                        Nothing -> ""                     , ( T.concat                       . map (formatExport exportSymbol)                       . Set.toList ) symbols] --- | Format the list of methods.-formatMethods :: [Export] -> Maybe Text-formatMethods = formatSection "Methods" toMethod-    where toMethod :: Export -> Maybe (Subsection, Export)-          toMethod e@(Export (ExportMethod s) _ _) =-            Just (subsecWithPrefix "method" s, e)-          toMethod _ = Nothing---- | Format the list of properties.-formatProperties :: [Export] -> Maybe Text-formatProperties = formatSection "Properties" toProperty-    where toProperty :: Export -> Maybe (Subsection, Export)-          toProperty e@(Export (ExportProperty s) _ _) =-            Just (subsecWithPrefix "attr" s, e)-          toProperty _ = Nothing+-- | Format the list of exports into grouped sections.+formatSubsectionExports :: M.Map HaddockSection Text -> [Export] -> [Maybe Text]+formatSubsectionExports docs exports = map (uncurry formatSection)+                                       (M.toAscList collectedExports)+  where collectedExports :: M.Map NamedSection [(Subsection, Export)]+        collectedExports = foldl classifyExport M.empty exports --- | Format the list of signals.-formatSignals :: [Export] -> Maybe Text-formatSignals = formatSection "Signals" toSignal-    where toSignal :: Export -> Maybe (Subsection, Export)-          toSignal e@(Export (ExportSignal s) _ _) =-            Just (subsecWithPrefix "signal" s, e)-          toSignal _ = Nothing+        classifyExport :: M.Map NamedSection [(Subsection, Export)] ->+                          Export -> M.Map NamedSection [(Subsection, Export)]+        classifyExport m export =+          case exportType export of+            ExportSymbol hs@(NamedSubsection ms n) ->+              let subsec = subsecWithPrefix ms n (M.lookup hs docs)+              in M.insertWith (++) ms [(subsec, export)] m+            _ -> m  -- | Format the given export list. This is just the inside of the -- parenthesis.-formatExportList :: [Export] -> Text-formatExportList exports =-    T.unlines . catMaybes $ [ formatExportedModules exports-                            , formatToplevel exports-                            , formatTypeDecls exports-                            , formatMethods exports-                            , formatProperties exports-                            , formatSignals exports ]+formatExportList :: M.Map HaddockSection Text -> [Export] -> Text+formatExportList docs exports =+    T.unlines . catMaybes $ formatExportedModules exports+                            : formatToplevel exports+                            : formatTypeDecls exports+                            : formatSubsectionExports docs exports  -- | Write down the list of language pragmas. languagePragmas :: [Text] -> Text@@ -772,6 +786,13 @@ ghcOptions [] = "" ghcOptions opts = "{-# OPTIONS_GHC " <> T.intercalate ", " opts <> " #-}\n" +-- | Generate some convenience CPP macros.+cppMacros :: Text+cppMacros = T.unlines ["#define ENABLE_OVERLOADING (MIN_VERSION_haskell_gi_overloading(1,0,0) \\"+                      -- Haddocks look better without overloading+                      , "       && !defined(__HADDOCK_VERSION__))"+                      ]+ -- | Standard fields for every module. standardFields :: Text standardFields = T.unlines [ "Copyright  : " <> authors@@ -785,22 +806,22 @@                                               description, "-}"]  -- | Generic module prelude. We reexport all of the submodules.-modulePrelude :: Text -> [Export] -> [Text] -> Text-modulePrelude name [] [] = "module " <> name <> " () where\n"-modulePrelude name exports [] =+modulePrelude :: M.Map HaddockSection Text -> Text -> [Export] -> [Text] -> Text+modulePrelude _ name [] [] = "module " <> name <> " () where\n"+modulePrelude docs name exports [] =     "module " <> name <> "\n    ( "-    <> formatExportList exports+    <> formatExportList docs exports     <> "    ) where\n"-modulePrelude name [] reexportedModules =+modulePrelude docs name [] reexportedModules =     "module " <> name <> "\n    ( "-    <> formatExportList (map (\m -> Export ExportModule m []) reexportedModules)+    <> formatExportList docs (map (\m -> Export ExportModule m []) reexportedModules)     <> "    ) where\n\n"     <> T.unlines (map ("import " <>) reexportedModules)-modulePrelude name exports reexportedModules =+modulePrelude docs name exports reexportedModules =     "module " <> name <> "\n    ( "-    <> formatExportList (map (\m -> Export ExportModule m []) reexportedModules)+    <> formatExportList docs (map (\m -> Export ExportModule m []) reexportedModules)     <> "\n"-    <> formatExportList exports+    <> formatExportList docs exports     <> "    ) where\n\n"     <> T.unlines (map ("import " <>) reexportedModules) @@ -833,6 +854,7 @@                 , "import qualified Data.GI.Base.ManagedPtr as B.ManagedPtr"                 , "import qualified Data.GI.Base.GError as B.GError"                 , "import qualified Data.GI.Base.GVariant as B.GVariant"+                , "import qualified Data.GI.Base.GValue as B.GValue"                 , "import qualified Data.GI.Base.GParamSpec as B.GParamSpec"                 , "import qualified Data.GI.Base.CallStack as B.CallStack"                 , "import qualified Data.Text as T"@@ -857,7 +879,8 @@       code = codeToText (moduleCode minfo)       pragmas = languagePragmas (Set.toList $ modulePragmas minfo)       optionsGHC = ghcOptions (Set.toList $ moduleGHCOpts minfo)-      prelude = modulePrelude (dotWithPrefix $ modulePath minfo)+      prelude = modulePrelude (sectionDocs minfo)+                (dotWithPrefix $ modulePath minfo)                 (F.toList (moduleExports minfo))                 submoduleExports       imports = if ImplicitPrelude `Set.member` moduleFlags minfo@@ -865,12 +888,12 @@                 else moduleImports       pkgRoot = ModulePath (take 1 (modulePathToList $ modulePath minfo))       deps = importDeps pkgRoot (Set.toList $ qualifiedImports minfo)-      haddock = moduleHaddock (moduleDoc minfo)+      haddock = moduleHaddock (M.lookup ToplevelSection (sectionDocs minfo))    when verbose $ putStrLn ((T.unpack . dotWithPrefix . modulePath) minfo                            ++ " -> " ++ fname)   createDirectoryIfMissing True dirname-  utf8WriteFile fname (T.unlines [pragmas, optionsGHC, haddock,+  utf8WriteFile fname (T.unlines [pragmas, optionsGHC, haddock, cppMacros,                                  prelude, imports, deps, code])   when (not . isCodeEmpty $ bootCode minfo) $ do     let bootFName = modulePathToFilePath dirPrefix (modulePath minfo) ".hs-boot"@@ -879,6 +902,7 @@ -- | Generate the .hs-boot file for the given module. genHsBoot :: ModuleInfo -> Text genHsBoot minfo =+    cppMacros <>     "module " <> (dotWithPrefix . modulePath) minfo <> " where\n\n" <>     moduleImports <> "\n" <>     codeToText (bootCode minfo)
lib/Data/GI/CodeGen/CodeGen.hs view
@@ -24,7 +24,9 @@ import Data.GI.CodeGen.Fixups (dropMovedItems, guessPropertyNullability,                                detectGObject) import Data.GI.CodeGen.GObject-import Data.GI.CodeGen.Haddock (deprecatedPragma, addModuleDocumentation)+import Data.GI.CodeGen.Haddock (deprecatedPragma, addSectionDocumentation,+                                writeHaddock,+                                RelativeDocPosition(DocBeforeSymbol)) import Data.GI.CodeGen.Inheritance (instanceTree, fullObjectMethodList,                        fullInterfaceMethodList) import Data.GI.CodeGen.Properties (genInterfaceProperties, genObjectProperties,@@ -52,7 +54,7 @@                            <> "\n-- Error was : " <> describeCGError e))                         (do                           genCCallableWrapper n symbol callable-                          exportMethod (lowerName n) (lowerName n)+                          export (NamedSubsection MethodSection $ lowerName n) (lowerName n)                         )  genBoxedObject :: Name -> Text -> CodeGen ()@@ -74,11 +76,12 @@ genStruct n s = unless (ignoreStruct n s) $ do    let name' = upperName n +   writeHaddock DocBeforeSymbol ("Memory-managed wrapper type.")    let decl = line $ "newtype " <> name' <> " = " <> name' <> " (ManagedPtr " <> name' <> ")"    hsBoot decl    decl -   addModuleDocumentation (structDocumentation s)+   addSectionDocumentation ToplevelSection (structDocumentation s)     if structIsBoxed s    then genBoxedObject n (fromJust $ structTypeInit s)@@ -116,11 +119,12 @@ genUnion n u = do   let name' = upperName n +  writeHaddock DocBeforeSymbol ("Memory-managed wrapper type.")   let decl = line $ "newtype " <> name' <> " = " <> name' <> " (ManagedPtr " <> name' <> ")"   hsBoot decl   decl -  addModuleDocumentation (unionDocumentation u)+  addSectionDocumentation ToplevelSection (unionDocumentation u)    if unionIsBoxed u   then genBoxedObject n (fromJust $ unionTypeInit u)@@ -225,7 +229,7 @@               then fixMethodArgs c'               else c'     genCCallableWrapper mn' sym c''-    exportMethod (lowerName mn) (lowerName mn')+    export (NamedSubsection MethodSection $ lowerName mn) (lowerName mn')      cppIf CPPOverloading $          genMethodInfo cn (m {methodCallable = c''})@@ -247,6 +251,8 @@   className <- classConstraint n   group $ do     exportDecl className+    writeHaddock DocBeforeSymbol (classDoc name')+     bline $ "class GObject o => " <> className <> " o"     line $ "#if MIN_VERSION_base(4,9,0)"     line $ "instance {-# OVERLAPPABLE #-} (GObject a, O.UnknownAncestorError "@@ -262,10 +268,20 @@   group $ do     let safeCast = "to" <> name'     exportDecl safeCast+    writeHaddock DocBeforeSymbol (castDoc name')     line $ safeCast <> " :: (MonadIO m, " <> className <> " o) => o -> m " <> name'     line $ safeCast <> " = liftIO . unsafeCastTo " <> name' --- Wrap a given Object. We enforce that every Object that we wrap is a+  where castDoc :: Text -> Text+        castDoc name' = "Cast to `" <> name' <>+                        "`, for types for which this is known to be safe. " <>+                        "For general casts, use `Data.GI.Base.ManagedPtr.castTo`."++        classDoc :: Text -> Text+        classDoc name' = "Type class for types which can be safely cast to `"+                         <> name' <> "`, for instance with `to" <> name' <> "`."++-- | Wrap a given Object. We enforce that every Object that we wrap is a -- GObject. This is the case for everything except the ParamSpec* set -- of objects, we deal with these separately. genObject :: Name -> Object -> CodeGen ()@@ -278,10 +294,11 @@   then line $ "-- APIObject \"" <> name' <>                 "\" does not descend from GObject, it will be ignored."   else do+    writeHaddock DocBeforeSymbol ("Memory-managed wrapper type.")     bline $ "newtype " <> name' <> " = " <> name' <> " (ManagedPtr " <> name' <> ")"     exportDecl (name' <> "(..)") -    addModuleDocumentation (objDocumentation o)+    addSectionDocumentation ToplevelSection (objDocumentation o)      -- Type safe casting to parent objects, and implemented interfaces.     parents <- instanceTree n@@ -320,11 +337,12 @@   let name' = upperName n    line $ "-- interface " <> name' <> " "+  writeHaddock DocBeforeSymbol ("Memory-managed wrapper type.")   deprecatedPragma name' $ ifDeprecated iface   bline $ "newtype " <> name' <> " = " <> name' <> " (ManagedPtr " <> name' <> ")"   exportDecl (name' <> "(..)") -  addModuleDocumentation (ifDocumentation iface)+  addSectionDocumentation ToplevelSection (ifDocumentation iface)    noName name' @@ -353,6 +371,9 @@   else group $ do     cls <- classConstraint n     exportDecl cls+    writeHaddock DocBeforeSymbol ("Type class for types which implement `"+                                  <> name' <> "`.")+     bline $ "class ManagedPtrNewtype a => " <> cls <> " a"     line $ "instance " <> cls <> " " <> name'     genWrappedPtr n (ifAllocationInfo iface) 0
lib/Data/GI/CodeGen/Constant.hs view
@@ -50,7 +50,7 @@   handleCGExc (\e -> line $ "-- XXX: Could not generate constant: " <> describeCGError e)     (do writeDocumentation DocBeforeSymbol (constantDocumentation c)         assignValue name (constantType c) (constantValue c)-        exportToplevel ("pattern " <> name))+        export ToplevelSection ("pattern " <> name))  -- | Assign to the given name the given constant value, in a way that -- can be assigned to the corresponding Haskell type.
lib/Data/GI/CodeGen/Conversions.hs view
@@ -164,7 +164,7 @@            genConversion l next     Literal Id next -> genConversion l next --- Given an array, together with its type, return the code for reading+-- | Given an array, together with its type, return the code for reading -- its length. computeArrayLength :: Text -> Type -> ExcCodeGen Text computeArrayLength array (TCArray _ _ _ t) = do@@ -371,8 +371,6 @@ hToF (TGArray t) transfer = hToF_PackedType t "packGArray" transfer hToF (TPtrArray t) transfer = hToF_PackedType t "packGPtrArray" transfer hToF (TGHash ta tb) _ = hToF_PackGHashTable ta tb--- Arrays without length info are just passed along.-hToF (TCArray False (-1) (-1) _) _ = return $ Pure () hToF (TCArray zt _ _ t@(TCArray{})) transfer = do   let packer = if zt                then "packZeroTerminated"@@ -453,14 +451,14 @@ fVariantToH :: Transfer -> CodeGen Constructor fVariantToH transfer =   return $ M $ case transfer of-                  TransferEverything -> "wrapGVariantPtr"-                  _ -> "newGVariantFromPtr"+                  TransferEverything -> "B.GVariant.wrapGVariantPtr"+                  _ -> "B.GVariant.newGVariantFromPtr"  fParamSpecToH :: Transfer -> CodeGen Constructor fParamSpecToH transfer =   return $ M $ case transfer of-                  TransferEverything -> "wrapGParamSpecPtr"-                  _ -> "newGParamSpecFromPtr"+                  TransferEverything -> "B.GParamSpec.wrapGParamSpecPtr"+                  _ -> "B.GParamSpec.newGParamSpecFromPtr"  fToH' :: Type -> Maybe API -> TypeRep -> TypeRep -> Transfer          -> ExcCodeGen Constructor@@ -545,20 +543,22 @@ fToH (TGList t) transfer = do   isPtr <- typeIsPtr t   when (not isPtr) $-       badIntroError ("'" <> tshow t <>+       badIntroError ("`" <> tshow t <>                       "' is not a pointer type, cannot unpack from a GList.")   fToH_PackedType t "unpackGList" transfer fToH (TGSList t) transfer = do   isPtr <- typeIsPtr t   when (not isPtr) $-       badIntroError ("'" <> tshow t <>+       badIntroError ("`" <> tshow t <>                       "' is not a pointer type, cannot unpack from a GSList.")   fToH_PackedType t "unpackGSList" transfer fToH (TGArray t) transfer = fToH_PackedType t "unpackGArray" transfer fToH (TPtrArray t) transfer = fToH_PackedType t "unpackGPtrArray" transfer fToH (TGHash a b) transfer = fToH_UnpackGHashTable a b transfer--- Arrays without length info are just passed along.-fToH (TCArray False (-1) (-1) _) _ = return $ Pure ()+-- We cannot unpack arrays without any kind of length info.+fToH t@(TCArray False (-1) (-1) _) _ =+  badIntroError ("`" <> tshow t <>+                  "' is an array type, but contains no length information.") fToH (TCArray True _ _ t@(TCArray{})) transfer =   fToH_PackedType t "unpackZeroTerminatedPtrArray" transfer fToH (TCArray True _ _ t@(TInterface _)) transfer = do@@ -662,7 +662,7 @@  unpackCArray _ _ _ = notImplementedError "unpackCArray : unexpected array type." --- Given a type find the typeclasses the type belongs to, and return+-- | Given a type find the typeclasses the type belongs to, and return -- the representation of the type in the function signature and the -- list of typeclass constraints for the type. argumentType :: [Char] -> Type -> CodeGen ([Char], Text, [Text])@@ -731,15 +731,15 @@ haskellBasicType TIntPtr   = con0 "CIntPtr" haskellBasicType TUIntPtr  = con0 "CUIntPtr" --- This translates GI types to the types used for generated Haskell code.+-- | This translates GI types to the types used for generated Haskell code. haskellType :: Type -> CodeGen TypeRep haskellType (TBasicType bt) = return $ haskellBasicType bt--- We cannot really do anything sensible for a foreign array with no--- length info, so just pass the pointer along.-haskellType (TCArray False (-1) (-1) t) =-    ptr <$> foreignType t+-- There is no great choice in this case, so we simply pass the+-- pointer along. This is useful for GdkPixbufNotify, for example.+haskellType t@(TCArray False (-1) (-1) (TBasicType TUInt8)) =+  foreignType t haskellType (TCArray _ _ _ (TBasicType TUInt8)) =-    return $ "ByteString" `con` []+  return $ "ByteString" `con` [] haskellType (TCArray _ _ _ a) = do   inner <- haskellType a   return $ "[]" `con` [inner]@@ -763,8 +763,8 @@ haskellType TError = return $ "GError" `con` [] haskellType TVariant = return $ "GVariant" `con` [] haskellType TParamSpec = return $ "GParamSpec" `con` []-haskellType (TInterface (Name "GObject" "Value")) = return $ "GValue" `con` [] haskellType (TInterface (Name "GObject" "Closure")) = return $ "Closure" `con` []+haskellType (TInterface (Name "GObject" "Value")) = return $ "GValue" `con` [] haskellType t@(TInterface n) = do   api <- getAPI t   tname <- qualifiedAPI n@@ -807,8 +807,6 @@ -- This translates GI types to the types used in foreign function calls. foreignType :: Type -> CodeGen TypeRep foreignType (TBasicType t) = return $ foreignBasicType t-foreignType (TCArray False (-1) (-1) t) =-    ptr <$> foreignType t foreignType (TCArray zt _ _ t) = do   api <- findAPI t   let size = case api of@@ -838,9 +836,10 @@ foreignType t@TError = ptr <$> haskellType t foreignType t@TVariant = ptr <$> haskellType t foreignType t@TParamSpec = ptr <$> haskellType t-foreignType (TInterface (Name "GObject" "Value")) = return $ ptr $ "GValue" `con` [] foreignType (TInterface (Name "GObject" "Closure")) =     return $ ptr $ "Closure" `con` []+foreignType (TInterface (Name "GObject" "Value")) =+  return $ ptr $ "GValue" `con` [] foreignType t@(TInterface n) = do   isScalar <- getIsScalar t   if isScalar@@ -955,11 +954,9 @@ typeIsNullable :: Type -> CodeGen Bool typeIsNullable t = isJust <$> maybeNullConvert t --- If the given type maps to a list in Haskell, return the type of the+-- | If the given type maps to a list in Haskell, return the type of the -- elements, and the function that maps over them. elementTypeAndMap :: Type -> Text -> Maybe (Type, Text)--- Passed along as a raw pointer.-elementTypeAndMap (TCArray False (-1) (-1) _) _ = Nothing -- ByteString elementTypeAndMap (TCArray _ _ _ (TBasicType TUInt8)) _ = Nothing elementTypeAndMap (TCArray True _ _ t) _ = Just (t, "mapZeroTerminatedCArray")
lib/Data/GI/CodeGen/EnumFlags.hs view
@@ -18,8 +18,8 @@ import Data.GI.CodeGen.SymbolNaming (upperName) import Data.GI.CodeGen.Util (tshow) -genEnumOrFlags :: Name -> Enumeration -> ExcCodeGen ()-genEnumOrFlags n@(Name ns name) e = do+genEnumOrFlags :: HaddockSection -> Name -> Enumeration -> ExcCodeGen ()+genEnumOrFlags docSection n@(Name ns name) e = do   -- Conversion functions expect enums and flags to map to CUInt,   -- which we assume to be of 32 bits. Fail early, instead of giving   -- strange errors at runtime.@@ -36,7 +36,7 @@   deprecatedPragma name' (enumDeprecated e)    group $ do-    exportDecl (name' <> "(..)")+    export docSection (name' <> "(..)")     hsBoot . line $ "data " <> name'     writeDocumentation DocBeforeSymbol (enumDocumentation e)     line $ "data " <> name' <> " = "@@ -69,7 +69,7 @@     line $ "instance P.Ord " <> name' <> " where"     indent $ line "compare a b = P.compare (P.fromEnum a) (P.fromEnum b)" -  maybe (return ()) (genErrorDomain name') (enumErrorDomain e)+  maybe (return ()) (genErrorDomain docSection name') (enumErrorDomain e)  genBoxedEnum :: Name -> Text -> CodeGen () genBoxedEnum n typeInit = do@@ -87,8 +87,9 @@ genEnum n@(Name _ name) enum = do   line $ "-- Enum " <> name +  let docSection = NamedSubsection EnumSection (upperName n)   handleCGExc (\e -> line $ "-- XXX Could not generate: " <> describeCGError e)-              (do genEnumOrFlags n enum+              (do genEnumOrFlags docSection n enum                   case enumTypeInit enum of                     Nothing -> return ()                     Just ti -> genBoxedEnum n ti)@@ -111,9 +112,10 @@ genFlags n@(Name _ name) (Flags enum) = do   line $ "-- Flags " <> name +  let docSection = NamedSubsection FlagSection (upperName n)   handleCGExc (\e -> line $ "-- XXX Could not generate: " <> describeCGError e)               (do-                genEnumOrFlags n enum+                genEnumOrFlags docSection n enum                  case enumTypeInit enum of                   Nothing -> return ()@@ -123,8 +125,8 @@                 group $ bline $ "instance IsGFlag " <> name')  -- | Support for enums encapsulating error codes.-genErrorDomain :: Text -> Text -> CodeGen ()-genErrorDomain name' domain = do+genErrorDomain :: HaddockSection -> Text -> Text -> CodeGen ()+genErrorDomain docSection name' domain = do   group $ do     line $ "instance GErrorClass " <> name' <> " where"     indent $ line $@@ -133,19 +135,29 @@   -- it's clearer to read).   group $ do     let catcher = "catch" <> name'+    writeHaddock DocBeforeSymbol catcherDoc     line $ catcher <> " ::"     indent $ do             line   "IO a ->"             line $ "(" <> name' <> " -> GErrorMessage -> IO a) ->"             line   "IO a"     line $ catcher <> " = catchGErrorJustDomain"+   group $ do     let handler = "handle" <> name'+    writeHaddock DocBeforeSymbol handleDoc     line $ handler <> " ::"     indent $ do             line $ "(" <> name' <> " -> GErrorMessage -> IO a) ->"             line   "IO a ->"             line   "IO a"     line $ handler <> " = handleGErrorJustDomain"-  exportToplevel ("catch" <> name')-  exportToplevel ("handle" <> name')+  export docSection ("catch" <> name')+  export docSection ("handle" <> name')++  where+    catcherDoc :: Text+    catcherDoc = "Catch exceptions of type `" <> name' <> "`. This is a specialized version of `Data.GI.Base.GError.catchGErrorJustDomain`."++    handleDoc :: Text+    handleDoc = "Handle exceptions of type `" <> name' <> "`. This is a specialized version of `Data.GI.Base.GError.handleGErrorJustDomain`."
lib/Data/GI/CodeGen/Haddock.hs view
@@ -7,14 +7,13 @@   , writeHaddock   , writeArgDocumentation   , writeReturnDocumentation-  , addModuleDocumentation+  , addSectionDocumentation   ) where  #if !MIN_VERSION_base(4,8,0) import Control.Applicative ((<$>)) #endif import Control.Monad (mapM_, unless)-import Control.Monad.State.Strict (modify') import qualified Data.Map as M import Data.Monoid ((<>)) import qualified Data.Text as T@@ -25,8 +24,8 @@ import Data.GI.GIR.Deprecation (DeprecationInfo(..)) import Data.GI.GIR.Documentation (Documentation(..)) -import Data.GI.CodeGen.Code (CodeGen, config, line, blank,-                             getC2HMap, ModuleInfo(moduleDoc))+import Data.GI.CodeGen.Code (CodeGen, config, line, HaddockSection,+                             getC2HMap, addSectionFormattedDocs) import Data.GI.CodeGen.Config (modName, overrides) import Data.GI.CodeGen.CtoHaskellMap (Hyperlink(..)) import Data.GI.CodeGen.GtkDoc (GtkDoc(..), Token(..), CRef(..), Language(..),@@ -207,23 +206,27 @@                        Nothing -> []                        Just v -> ["(Since version " <> v <> ")"] --- | Write the given documentation into a Haddock comment.-writeDocumentation :: RelativeDocPosition -> Documentation -> CodeGen ()-writeDocumentation pos doc = do-  c2h <- getC2HMap-  docBase <- getDocBase+-- | Format the given documentation into a set of lines. Note that+-- this does include the opening or ending comment delimiters.+formatDocumentation :: M.Map CRef Hyperlink -> Text -> Documentation -> Text+formatDocumentation c2h docBase doc = do   let description = case rawDocText doc of         Just raw -> formatHaddock c2h docBase (parseGtkDoc raw)         Nothing -> "/No description available in the introspection data./"+  description <> case sinceVersion doc of+                   Nothing -> ""+                   Just ver -> "\n\n@since " <> ver++-- | Write the given documentation into generated code.+writeDocumentation :: RelativeDocPosition -> Documentation -> CodeGen ()+writeDocumentation pos doc = do   line $ case pos of            DocBeforeSymbol -> "{- |"            DocAfterSymbol ->  "{- ^"-  mapM_ line (T.lines description)-  case sinceVersion doc of-    Nothing -> return ()-    Just ver -> do-      blank-      line $ "@since " <> ver+  c2h <- getC2HMap+  docBase <- getDocBase+  let haddock = formatDocumentation c2h docBase doc+  mapM_ line (T.lines haddock)   line "-}"  -- | Like `writeDocumentation`, but allows us to pass explicitly the@@ -270,15 +273,10 @@   unless (T.null fullInfo) $     line $ "{- ^ " <>  fullInfo <> " -}" --- | Add the given text to the module-level documentation for the--- module being generated.-addModuleDocumentation :: Documentation -> CodeGen ()-addModuleDocumentation doc =-  case rawDocText doc of-    Nothing -> return ()-    Just raw -> do-      c2h <- getC2HMap-      docBase <- getDocBase-      modify' $ \(cgs, s) -> (cgs, s{moduleDoc = moduleDoc s <>-                                      Just (formatHaddock c2h docBase-                                            (parseGtkDoc raw))})+-- | Add the given text to the documentation for the section being generated.+addSectionDocumentation :: HaddockSection -> Documentation -> CodeGen ()+addSectionDocumentation section doc = do+  c2h <- getC2HMap+  docBase <- getDocBase+  let formatted = formatDocumentation c2h docBase doc+  addSectionFormattedDocs section formatted
lib/Data/GI/CodeGen/ModulePath.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-} -- | Abstract representation for paths into modules. module Data.GI.CodeGen.ModulePath   ( ModulePath(..)@@ -9,22 +10,18 @@ import Data.Monoid (Monoid(..), (<>)) import Data.String (IsString(..)) import qualified Data.Text as T+import qualified Data.Semigroup as Sem import Data.Text (Text)  import Data.GI.CodeGen.Util (ucFirst)  -- | A path to a module. newtype ModulePath = ModulePath { modulePathToList :: [Text] }-  deriving (Eq, Show, Ord)+  deriving (Sem.Semigroup, Monoid, Eq, Show, Ord)  -- | Construct a `ModulePath` from a `String`. instance IsString ModulePath where   fromString = toModulePath . T.pack---- | `ModulePath`s are `Monoid`s.-instance Monoid ModulePath where-  mempty = ModulePath []-  mappend (ModulePath as) (ModulePath bs) = ModulePath (as <> bs)  -- | Construct a path into the given GIR namespace. The given `Text` -- will be split along ".".
lib/Data/GI/CodeGen/OverloadedLabels.hs view
@@ -78,11 +78,11 @@   line $ "_" <> l <> " :: IsLabelProxy \"" <> l <> "\" a => a"   line $ "_" <> l <> " = fromLabelProxy (Proxy :: Proxy \""            <> l <> "\")"-  exportToplevel ("_" <> l)+  export ToplevelSection ("_" <> l)  genOverloadedLabels :: [(Name, API)] -> CodeGen () genOverloadedLabels allAPIs = do-  setLanguagePragmas ["DataKinds", "FlexibleContexts"]+  setLanguagePragmas ["DataKinds", "FlexibleContexts", "CPP"]   setModuleFlags [ImplicitPrelude]    line $ "import Data.Proxy (Proxy(..))"
lib/Data/GI/CodeGen/OverloadedMethods.hs view
@@ -96,7 +96,7 @@         let mn = methodName m             mangled = lowerName (mn {name = name n <> "_" <> name mn})         indent $ line $ "overloadedMethod _ = " <> mangled-        exportMethod (lowerName mn) infoName+        export (NamedSubsection MethodSection $ lowerName mn) infoName  -- | Generate a method info that is not actually callable, but rather -- gives a type error when trying to use it.@@ -110,4 +110,4 @@            <> lowerName (methodName m) <> "\" " <> name n            <> ") => O.MethodInfo " <> infoName <> " o p where"   indent $ line $ "overloadedMethod _ = undefined"-  exportMethod "Unsupported methods" infoName+  export ToplevelSection infoName
lib/Data/GI/CodeGen/OverloadedSignals.hs view
@@ -88,7 +88,7 @@       line $ "type HaskellCallbackType " <> si <> " = " <> cbHaskellType       line $ "connectSignal _ obj cb connectMode = do"       indent $ genSignalConnector signal cbHaskellType "connectMode"-  exportSignal (lcFirst sn) si+  export (NamedSubsection SignalSection $ lcFirst sn) si  -- | Signal instances for (GObject-derived) objects. genObjectSignals :: Name -> Object -> CodeGen ()
lib/Data/GI/CodeGen/Overrides.hs view
@@ -13,10 +13,11 @@  import Control.Monad.Except import Control.Monad.State-import Control.Monad.Writer+import Control.Monad.Writer (WriterT, execWriterT, tell)  import Data.Maybe (isJust) import qualified Data.Map as M+import Data.Semigroup as Sem import qualified Data.Set as S import qualified Data.Text as T import Data.Text (Text)@@ -72,8 +73,18 @@ -- encode this so that we can view the parser as a writer monad of -- configs. instance Monoid Overrides where-    mempty = defaultOverrides-    mappend a b = Overrides {+  mempty = defaultOverrides+#if !MIN_VERSION_base(4,11,0)+  mappend = concatOverrides+#endif++-- | There is a sensible notion of zero and addition of Overridess,+-- encode this so that we can view the parser as a writer monad of+-- configs.+instance Sem.Semigroup Overrides where+  (<>) = concatOverrides++concatOverrides a b = Overrides {       ignoredAPIs = ignoredAPIs a <> ignoredAPIs b,       sealedStructs = sealedStructs a <> sealedStructs b,       allocInfo = allocInfo a <> allocInfo b,
lib/Data/GI/CodeGen/Properties.hs view
@@ -20,6 +20,8 @@ import Data.GI.CodeGen.Conversions import Data.GI.CodeGen.Code import Data.GI.CodeGen.GObject+import Data.GI.CodeGen.Haddock (addSectionDocumentation, writeHaddock,+                                RelativeDocPosition(DocBeforeSymbol)) import Data.GI.CodeGen.Inheritance (fullObjectPropertyList, fullInterfacePropertyList) import Data.GI.CodeGen.SymbolNaming (lowerName, upperName,                                      classConstraint, typeConstraint,@@ -88,13 +90,25 @@   (_,t,constraints) <- argumentType ['a'..'l'] $ propType prop   return (constraints, t) -genPropertySetter :: Text -> Name -> Text -> Property -> CodeGen ()+-- | Generate documentation for the given setter.+setterDoc :: Name -> Property -> Text+setterDoc n prop = T.unlines [+    "Set the value of the “@" <> propName prop <> "@” property."+  , "When <https://github.com/haskell-gi/haskell-gi/wiki/Overloading overloading> is enabled, this is equivalent to"+  , ""+  , "@"+  , "'Data.GI.Base.Attributes.set' " <> lowerName n <> " [ #" <> hPropName prop+    <> " 'Data.GI.Base.Attributes.:=' value ]"+  , "@"]++genPropertySetter :: Text -> Name -> HaddockSection -> Property -> CodeGen () genPropertySetter setter n docSection prop = group $ do   (constraints, t) <- attrType prop   isNullable <- typeIsNullable (propType prop)   cls <- classConstraint n   let constraints' = "MonadIO m":(cls <> " o"):constraints   tStr <- propTypeStr $ propType prop+  writeHaddock DocBeforeSymbol (setterDoc n prop)   line $ setter <> " :: (" <> T.intercalate ", " constraints'            <> ") => o -> " <> t <> " -> m ()"   line $ setter <> " obj val = liftIO $ setObjectProperty" <> tStr@@ -102,9 +116,19 @@            <> if isNullable               then "\" (Just val)"               else "\" val"-  exportProperty docSection setter+  export docSection setter -genPropertyGetter :: Text -> Name -> Text -> Property -> CodeGen ()+-- | Generate documentation for the given getter.+getterDoc :: Name -> Property -> Text+getterDoc n prop = T.unlines [+    "Get the value of the “@" <> propName prop <> "@” property."+  , "When <https://github.com/haskell-gi/haskell-gi/wiki/Overloading overloading> is enabled, this is equivalent to"+  , ""+  , "@"+  , "'Data.GI.Base.Attributes.get' " <> lowerName n <> " #" <> hPropName prop+  , "@"]++genPropertyGetter :: Text -> Name -> HaddockSection -> Property -> CodeGen () genPropertyGetter getter n docSection prop = group $ do   isNullable <- typeIsNullable (propType prop)   let isMaybe = isNullable && propReadNullable prop /= Just False@@ -119,6 +143,7 @@                 then "checkUnexpectedNothing \"" <> getter                          <> "\" $ getObjectProperty" <> tStr                 else "getObjectProperty" <> tStr+  writeHaddock DocBeforeSymbol (getterDoc n prop)   line $ getter <> " :: " <> constraints <>                 " => o -> " <> typeShow ("m" `con` [outType])   line $ getter <> " obj = liftIO $ " <> getProp@@ -126,9 +151,15 @@            if tStr `elem` ["Object", "Boxed"]            then " " <> typeShow constructorType -- These require the constructor.            else ""-  exportProperty docSection getter+  export docSection getter -genPropertyConstructor :: Text -> Name -> Text -> Property -> CodeGen ()+-- | Generate documentation for the given constructor.+constructorDoc :: Property -> Text+constructorDoc prop = T.unlines [+    "Construct a `GValueConstruct` with valid value for the “@" <> propName prop <> "@” property. This is rarely needed directly, but it is used by `Data.GI.Base.Constructible.new`."+    ]++genPropertyConstructor :: Text -> Name -> HaddockSection -> Property -> CodeGen () genPropertyConstructor constructor n docSection prop = group $ do   (constraints, t) <- attrType prop   tStr <- propTypeStr $ propType prop@@ -136,6 +167,7 @@   cls <- classConstraint n   let constraints' = (cls <> " o") : constraints       pconstraints = parenthesize (T.intercalate ", " constraints') <> " => "+  writeHaddock DocBeforeSymbol (constructorDoc prop)   line $ constructor <> " :: " <> pconstraints            <> t <> " -> IO (GValueConstruct o)"   line $ constructor <> " val = constructObjectProperty" <> tStr@@ -143,20 +175,31 @@            <> if isNullable               then "\" (Just val)"               else "\" val"-  exportProperty docSection constructor+  export docSection constructor -genPropertyClear :: Text -> Name -> Text -> Property -> CodeGen ()+-- | Generate documentation for the given setter.+clearDoc :: Property -> Text+clearDoc prop = T.unlines [+    "Set the value of the “@" <> propName prop <> "@” property to `Nothing`."+  , "When <https://github.com/haskell-gi/haskell-gi/wiki/Overloading overloading> is enabled, this is equivalent to"+  , ""+  , "@"+  , "'Data.GI.Base.Attributes.clear'" <> " #" <> hPropName prop+  , "@"]++genPropertyClear :: Text -> Name -> HaddockSection -> Property -> CodeGen () genPropertyClear clear n docSection prop = group $ do   nothingType <- typeShow . maybeT <$> haskellType (propType prop)   cls <- classConstraint n   let constraints = ["MonadIO m", cls <> " o"]   tStr <- propTypeStr $ propType prop+  writeHaddock DocBeforeSymbol (clearDoc prop)   line $ clear <> " :: (" <> T.intercalate ", " constraints            <> ") => o -> m ()"   line $ clear <> " obj = liftIO $ setObjectProperty" <> tStr            <> " obj \"" <> propName prop <> "\" (Nothing :: "            <> nothingType <> ")"-  exportProperty docSection clear+  export docSection clear  -- | The property name as a lexically valid Haskell identifier. Note -- that this is not escaped, since it is assumed that it will be used@@ -207,7 +250,7 @@ genOneProperty owner prop = do   let name = upperName owner       cName = (hyphensToCamelCase . propName) prop-      docSection = lcFirst cName+      docSection = NamedSubsection PropertySection (lcFirst cName)       pName = name <> cName       flags = propFlags prop       writable = PropertyWritable `elem` flags &&@@ -215,6 +258,8 @@       readable = PropertyReadable `elem` flags       constructOnly = PropertyConstructOnly `elem` flags +  addSectionDocumentation docSection (propDoc prop)+   -- For properties the meaning of having transfer /= TransferNothing   -- is not clear (what are the right semantics for GValue setters?),   -- and the other possibilities are very uncommon, so let us just@@ -287,7 +332,7 @@                          then ["'AttrClear"]                          else [])     it <- infoType owner prop-    exportProperty docSection it+    export docSection it     bline $ "data " <> it     line $ "instance AttrInfo " <> it <> " where"     indent $ do@@ -311,8 +356,8 @@   line $ "-- XXX Placeholder"   it <- infoType owner prop   let cName = (hyphensToCamelCase . propName) prop-      docSection = lcFirst cName-  exportProperty docSection it+      docSection = NamedSubsection PropertySection (lcFirst cName)+  export docSection it   line $ "data " <> it   line $ "instance AttrInfo " <> it <> " where"   indent $ do@@ -367,9 +412,9 @@   forM_ filteredAttrs $ \attr -> group $ do     let cName = ucFirst attr         labelProxy = lcFirst name <> cName-        docSection = lcFirst cName+        docSection = NamedSubsection PropertySection (lcFirst cName)      line $ labelProxy <> " :: AttrLabelProxy \"" <> lcFirst cName <> "\""     line $ labelProxy <> " = AttrLabelProxy" -    exportProperty docSection labelProxy+    export docSection labelProxy
lib/Data/GI/CodeGen/Signal.hs view
@@ -25,49 +25,70 @@                                  callableHInArgs, callableHOutArgs) import Data.GI.CodeGen.Code import Data.GI.CodeGen.Conversions-import Data.GI.CodeGen.Haddock (deprecatedPragma)+import Data.GI.CodeGen.Haddock (deprecatedPragma,+                                RelativeDocPosition(..), writeHaddock,+                                writeDocumentation,+                                writeArgDocumentation, writeReturnDocumentation) import Data.GI.CodeGen.SymbolNaming import Data.GI.CodeGen.Transfer (freeContainerType) import Data.GI.CodeGen.Type import Data.GI.CodeGen.Util (parenthesize, withComment, tshow, terror,                              lcFirst, ucFirst, prime)+import Data.GI.GIR.Documentation (Documentation)  -- | The prototype of the callback on the Haskell side (what users of -- the binding will see) genHaskellCallbackPrototype :: Text -> Callable -> Text -> ExposeClosures ->-                               ExcCodeGen ()-genHaskellCallbackPrototype subsec cb htype expose = group $ do+                               Documentation -> ExcCodeGen ()+genHaskellCallbackPrototype subsec cb htype expose doc = group $ do     let name' = case expose of                   WithClosures -> callbackHTypeWithClosures htype                   WithoutClosures -> htype         (hInArgs, _) = callableHInArgs cb expose+        inArgsWithArrows = zip ("" : repeat "-> ") hInArgs         hOutArgs = callableHOutArgs cb -    exportSignal subsec name'+    export (NamedSubsection SignalSection subsec) name'+    writeDocumentation DocBeforeSymbol doc     line $ "type " <> name' <> " ="     indent $ do-      forM_ hInArgs $ \arg -> do+      forM_ inArgsWithArrows $ \(arrow, arg) -> do         ht <- haskellType (argType arg)-        wrapMaybe arg >>= bool-                          (line $ typeShow ht <> " ->")-                          (line $ typeShow (maybeT ht) <> " ->")+        isMaybe <- wrapMaybe arg+        let formattedType = if isMaybe+                            then typeShow (maybeT ht)+                            else typeShow ht+        line $ arrow <> formattedType+        writeArgDocumentation arg       ret <- hOutType cb hOutArgs-      line $ typeShow $ io ret+      let returnArrow = if null hInArgs+                        then ""+                        else "-> "+      line $ returnArrow <> typeShow (io ret)+      writeReturnDocumentation cb False      blank      -- For optional parameters, in case we want to pass Nothing.-    exportSignal subsec ("no" <> name')+    export (NamedSubsection SignalSection subsec) ("no" <> name')+    writeHaddock DocBeforeSymbol (noCallbackDoc name')     line $ "no" <> name' <> " :: Maybe " <> name'     line $ "no" <> name' <> " = Nothing" +  where noCallbackDoc :: Text -> Text+        noCallbackDoc typeName =+          "A convenience synonym for @`Nothing` :: `Maybe` `" <> typeName <>+          "`@."+ -- | Generate the type synonym for the prototype of the callback on -- the C side. Returns the name given to the type synonym. genCCallbackPrototype :: Text -> Callable -> Text -> Bool -> CodeGen Text genCCallbackPrototype subsec cb name' isSignal = group $ do     let ctypeName = callbackCType name'-    exportSignal subsec ctypeName +    export (NamedSubsection SignalSection subsec) ctypeName+    writeHaddock DocBeforeSymbol ccallbackDoc+     line $ "type " <> ctypeName <> " ="     indent $ do       when isSignal $ line $ withComment "Ptr () ->" "object"@@ -86,15 +107,24 @@       line $ typeShow ret     return ctypeName --- Generator for wrappers callable from C+  where+    ccallbackDoc :: Text+    ccallbackDoc = "Type for the callback on the (unwrapped) C side."++-- | Generator for wrappers callable from C genCallbackWrapperFactory :: Text -> Text -> CodeGen () genCallbackWrapperFactory subsec name' = group $ do     let factoryName = callbackWrapperAllocator name'+    writeHaddock DocBeforeSymbol factoryDoc     line "foreign import ccall \"wrapper\""     indent $ line $ factoryName <> " :: " <> callbackCType name'                <> " -> IO (FunPtr " <> callbackCType name' <> ")"-    exportSignal subsec factoryName+    export (NamedSubsection SignalSection subsec) factoryName +  where factoryDoc :: Text+        factoryDoc = "Generate a function pointer callable from C code, from a `"+                     <> callbackCType name' <> "`."+ -- | Wrap the Haskell `cb` callback into a foreign function of the -- right type. Returns the name of the wrapped value. genWrappedCallback :: Callable -> Text -> Text -> Bool -> CodeGen Text@@ -116,7 +146,8 @@ genClosure :: Text -> Callable -> Text -> Text -> Bool -> CodeGen () genClosure subsec cb callback name isSignal = group $ do   let closure = callbackClosureGenerator name-  exportSignal subsec closure+  export (NamedSubsection SignalSection subsec) closure+  writeHaddock DocBeforeSymbol closureDoc   group $ do       line $ closure <> " :: " <> callback <> " -> IO Closure"       line $ closure <> " cb = do"@@ -124,6 +155,9 @@             wrapped <- genWrappedCallback cb "cb" callback isSignal             line $ callbackWrapperAllocator callback <> " " <> wrapped                      <> " >>= newCClosure"+  where+    closureDoc :: Text+    closureDoc = "Wrap the callback into a `Closure`."  -- Wrap a conversion of a nullable object into "Maybe" object, by -- checking whether the pointer is NULL.@@ -218,12 +252,16 @@                              else Nothing       argNames = map (maybe "_" id . passOrIgnore) inWithClosures -  exportSignal subsec dropper+  export (NamedSubsection SignalSection subsec) dropper+  writeHaddock DocBeforeSymbol dropperDoc    line $ dropper <> " :: " <> name' <> " -> " <> callbackHTypeWithClosures name'   line $ dropper <> " _f " <> T.unwords argNames <> " = _f "            <> T.unwords (catMaybes (map passOrIgnore inWithClosures)) +  where dropperDoc :: Text+        dropperDoc = "A simple wrapper that ignores the closure arguments."+ -- | The wrapper itself, marshalling to and from Haskell. The `Callable` -- argument is possibly a pointer to a FunPtr to free (via -- freeHaskellFunPtr) once the callback is run once, or Nothing if the@@ -235,8 +273,11 @@   let wrapperName = callbackHaskellToForeign name'       (hInArgs, _) = callableHInArgs cb WithClosures       hOutArgs = callableHOutArgs cb+      wrapperDoc = "Wrap a `" <> name' <> "` into a `" <>+                   callbackCType name' <> "`." -  exportSignal subsec wrapperName+  export (NamedSubsection SignalSection subsec) wrapperName+  writeHaddock DocBeforeSymbol wrapperDoc    group $ do     line $ wrapperName <> " ::"@@ -244,7 +285,6 @@       if isSignal       then do         line $ name' <> " ->"-        line "Ptr () ->"       else do            line $ "Maybe (Ptr (FunPtr " <> callbackCType name' <> ")) ->"            let hType = if callableHasClosures cb@@ -252,19 +292,7 @@                        else name'            line $ hType <> " ->" -      forM_ (args cb) $ \arg -> do-        ht <- foreignType $ argType arg-        let ht' = if direction arg /= DirectionIn-                  then ptr ht-                  else ht-        line $ typeShow ht' <> " ->"-      when (callableThrows cb) $-        line "Ptr (Ptr GError) ->"-      when isSignal $ line "Ptr () ->"-      ret <- io <$> case returnType cb of-                      Nothing -> return $ con0 "()"-                      Just t -> foreignType t-      line $ typeShow ret+      line $ callbackCType name'      let cArgNames = map escapedArgName (args cb)         allArgs = if isSignal@@ -304,7 +332,7 @@                line $ "return " <> result'  genCallback :: Name -> Callback -> CodeGen ()-genCallback n (Callback {cbCallable = cb}) = do+genCallback n (Callback {cbCallable = cb, cbDocumentation = cbDoc }) = do   let name' = upperName n   line $ "-- callback " <> name'   line $ "--          -> " <> tshow (fixupCallerAllocates cb)@@ -322,12 +350,12 @@                              "\n-- Error was : " <> describeCGError e)) $ do       typeSynonym <- genCCallbackPrototype name' cb' name' False       dynamic <- genDynamicCallableWrapper n typeSynonym cb-      exportSignal name' dynamic+      export (NamedSubsection SignalSection name') dynamic       genCallbackWrapperFactory name' name'       deprecatedPragma name' (callableDeprecated cb')-      genHaskellCallbackPrototype name' cb' name' WithoutClosures+      genHaskellCallbackPrototype name' cb' name' WithoutClosures cbDoc       when (callableHasClosures cb') $ do-           genHaskellCallbackPrototype name' cb' name' WithClosures+           genHaskellCallbackPrototype name' cb' name' WithClosures cbDoc            genDropClosures name' cb' name'       if callableThrows cb'       then do@@ -368,10 +396,12 @@   let sn' = signalHaskellName sn       signalConnectorName = on' <> ucFirst sn'       cbType = signalConnectorName <> "Callback"+      docSection = NamedSubsection SignalSection $ lcFirst sn'    deprecatedPragma cbType (callableDeprecated cb)-  genHaskellCallbackPrototype (lcFirst sn') cb cbType WithoutClosures +  genHaskellCallbackPrototype (lcFirst sn') cb cbType WithoutClosures (sigDoc s)+   _ <- genCCallbackPrototype (lcFirst sn') cb cbType True    genCallbackWrapperFactory (lcFirst sn') cbType@@ -400,16 +430,41 @@         afterName = "after" <> signalConnectorName      group $ do+      writeHaddock DocBeforeSymbol onDoc       line $ onName <> signature       line $ onName <> " obj cb = liftIO $ do"       indent $ genSignalConnector s cbType "SignalConnectBefore"-      exportSignal (lcFirst sn') onName+      export docSection onName      group $ do+      writeHaddock DocBeforeSymbol afterDoc       line $ afterName <> signature       line $ afterName <> " obj cb = liftIO $ do"       indent $ genSignalConnector s cbType "SignalConnectAfter"-      exportSignal (lcFirst sn') afterName+      export docSection afterName++  where+    onDoc :: Text+    onDoc = T.unlines [+      "Connect a signal handler for the “@" <> sn <>+        "@” signal, to be run before the default handler."+      , "When <https://github.com/haskell-gi/haskell-gi/wiki/Overloading overloading> is enabled, this is equivalent to"+      , ""+      , "@"+      , "'Data.GI.Base.Signals.on' " <> lowerName on <> " #"+        <> lcFirst (hyphensToCamelCase sn) <> " callback"+      , "@" ]++    afterDoc :: Text+    afterDoc = T.unlines [+      "Connect a signal handler for the “@" <> sn <>+        "@” signal, to be run after the default handler."+      , "When <https://github.com/haskell-gi/haskell-gi/wiki/Overloading overloading> is enabled, this is equivalent to"+      , ""+      , "@"+      , "'Data.GI.Base.Signals.after' " <> lowerName on <> " #"+        <> lcFirst (hyphensToCamelCase sn) <> " callback"+      , "@" ]  -- | Generate the code for connecting the given signal. This assumes -- that it lives inside a @do@ block.
lib/Data/GI/CodeGen/Struct.hs view
@@ -21,6 +21,8 @@ import Data.GI.CodeGen.API import Data.GI.CodeGen.Conversions import Data.GI.CodeGen.Code+import Data.GI.CodeGen.Haddock (addSectionDocumentation, writeHaddock,+                                RelativeDocPosition(DocBeforeSymbol)) import Data.GI.CodeGen.SymbolNaming import Data.GI.CodeGen.Type import Data.GI.CodeGen.Util@@ -95,6 +97,20 @@       Nothing -> badIntroError "Cannot determine whether the field is embedded."       Just isPtr -> return (not isPtr) +-- | Name for the getter function+fieldGetter :: Name -> Field -> Text+fieldGetter name' field = "get" <> upperName name' <> fName field++-- | Generate documentation for the given getter.+getterDoc :: Name -> Field -> Text+getterDoc n field = T.unlines [+    "Get the value of the “@" <> fieldName field <> "@” field."+  , "When <https://github.com/haskell-gi/haskell-gi/wiki/Overloading overloading> is enabled, this is equivalent to"+  , ""+  , "@"+  , "'Data.GI.Base.Attributes.get' " <> lowerName n <> " #" <> labelName field+  , "@"]+ -- Notice that when reading the field we return a copy of any embedded -- structs, so modifications of the returned struct will not affect -- the original struct. This is on purpose, in order to increase@@ -116,6 +132,8 @@                         else isoHaskellType (fieldType field)   fType <- typeShow <$> foreignType (fieldType field) +  writeHaddock DocBeforeSymbol (getterDoc n field)+   line $ getter <> " :: MonadIO m => " <> name' <> " -> m " <>               if T.any (== ' ') hType               then parenthesize hType@@ -140,6 +158,21 @@                 return "result"     line $ "return " <> result +-- | Name for the setter function+fieldSetter :: Name -> Field -> Text+fieldSetter name' field = "set" <> upperName name' <> fName field++-- | Generate documentation for the given setter.+setterDoc :: Name -> Field -> Text+setterDoc n field = T.unlines [+    "Set the value of the “@" <> fieldName field <> "@” field."+  , "When <https://github.com/haskell-gi/haskell-gi/wiki/Overloading overloading> is enabled, this is equivalent to"+  , ""+  , "@"+  , "'Data.GI.Base.Attributes.set' " <> lowerName n <> " [ #" <> labelName field+    <> " 'Data.GI.Base.Attributes.:=' value ]"+  , "@"]+ -- | Write a field into a struct. Note that, since we cannot know for -- sure who will be deallocating the fields in the struct, we leave -- any conversions that involve pointers to the caller. What this@@ -158,6 +191,8 @@            then return fType            else typeShow <$> haskellType (fieldType field) +  writeHaddock DocBeforeSymbol (setterDoc n field)+   line $ setter <> " :: MonadIO m => " <> name' <> " -> "            <> hType <> " -> m ()"   line $ setter <> " s val = liftIO $ withManagedPtr s $ \\ptr -> do"@@ -168,6 +203,20 @@     line $ "poke (ptr `plusPtr` " <> tshow (fieldOffset field)          <> ") (" <> converted <> " :: " <> fType <> ")" +-- | Name for the clear function+fieldClear :: Name -> Field -> Text+fieldClear name' field = "clear" <> upperName name' <> fName field++-- | Documentation for the @clear@ method.+clearDoc :: Field -> Text+clearDoc field = T.unlines [+  "Set the value of the “@" <> fieldName field <> "@” field to `Nothing`."+  , "When <https://github.com/haskell-gi/haskell-gi/wiki/Overloading overloading> is enabled, this is equivalent to"+  , ""+  , "@"+  , "'Data.GI.Base.Attributes.clear'" <> " #" <> labelName field+  , "@"]+ -- | Write a @NULL@ into a field of a struct of type `Ptr`. buildFieldClear :: Name -> Field -> Text -> ExcCodeGen () buildFieldClear n field nullPtr = group $ do@@ -176,28 +225,22 @@    fType <- typeShow <$> foreignType (fieldType field) +  writeHaddock DocBeforeSymbol (clearDoc field)+   line $ clear <> " :: MonadIO m => " <> name' <> " -> m ()"   line $ clear <> " s = liftIO $ withManagedPtr s $ \\ptr -> do"   indent $     line $ "poke (ptr `plusPtr` " <> tshow (fieldOffset field)          <> ") ("  <> nullPtr <> " :: " <> fType <> ")" --- | Name for the getter function-fieldGetter :: Name -> Field -> Text-fieldGetter name' field = "get" <> upperName name' <> fName field---- | Name for the setter function-fieldSetter :: Name -> Field -> Text-fieldSetter name' field = "set" <> upperName name' <> fName field---- | Name for the clear function-fieldClear :: Name -> Field -> Text-fieldClear name' field = "clear" <> upperName name' <> fName field- -- | Haskell name for the field fName :: Field -> Text fName = underscoresToCamelCase . fieldName +-- | Label associated to the field.+labelName :: Field -> Text+labelName = lcFirst  . fName+ -- | Support for modifying fields as attributes. Returns a tuple with -- the name of the overloaded label to be used for the field, and the -- associated info type.@@ -250,30 +293,33 @@     line $ labelProxy <> " :: AttrLabelProxy \"" <> lcFirst (fName field) <> "\""     line $ labelProxy <> " = AttrLabelProxy" -    exportProperty (lcFirst $ fName field) labelProxy+    export (NamedSubsection PropertySection $ lcFirst $ fName field) labelProxy -  return $ "'(\"" <> (lcFirst  . fName) field <> "\", " <> it <> ")"+  return $ "'(\"" <> labelName field <> "\", " <> it <> ")"  buildFieldAttributes :: Name -> Field -> ExcCodeGen (Maybe Text) buildFieldAttributes n field     | not (fieldVisible field) = return Nothing     | privateType (fieldType field) = return Nothing     | otherwise = group $ do+      nullPtr <- nullPtrForType (fieldType field)       embedded <- isEmbedded field +     addSectionDocumentation docSection (fieldDocumentation field)+      buildFieldReader n field-     exportProperty (lcFirst $ fName field) (fieldGetter n field)+     export docSection (fieldGetter n field)       when (not embedded) $ do          buildFieldWriter n field-         exportProperty (lcFirst $ fName field) (fieldSetter n field)+         export docSection (fieldSetter n field)           case nullPtr of            Just null -> do               buildFieldClear n field null-              exportProperty (lcFirst $ fName field) (fieldClear n field)+              export docSection (fieldClear n field)            Nothing -> return ()       Just <$> cppIf CPPOverloading (genAttrInfo n field)@@ -282,6 +328,8 @@           privateType (TInterface n) = "Private" `T.isSuffixOf` name n           privateType _ = False +          docSection = NamedSubsection PropertySection $ lcFirst $ fName field+ genStructOrUnionFields :: Name -> [Field] -> CodeGen () genStructOrUnionFields n fields = do   let name' = upperName n@@ -309,7 +357,10 @@       let name = upperName n       let builder = "newZero" <> name           tsize = tshow size-      line $ "-- | Construct a `" <> name <> "` struct initialized to zero."++      writeHaddock DocBeforeSymbol ("Construct a `" <> name <>+                                     "` struct initialized to zero.")+       line $ builder <> " :: MonadIO m => m " <> name       line $ builder <> " = liftIO $ " <>            if isBoxed
lib/Data/GI/CodeGen/SymbolNaming.hs view
@@ -159,9 +159,12 @@ -- want to pass Nothing. noName :: Text -> CodeGen () noName name' = group $ do-                 line $ "no" <> name' <> " :: Maybe " <> name'-                 line $ "no" <> name' <> " = Nothing"-                 exportDecl ("no" <> name')+  -- We should use `writeHaddock` here, but it would give rise to a+  -- cyclic import.+  line $ "-- | A convenience alias for `Nothing` :: `Maybe` `" <> name' <> "`."+  line $ "no" <> name' <> " :: Maybe " <> name'+  line $ "no" <> name' <> " = Nothing"+  exportDecl ("no" <> name')  -- | Turn a hyphen-separated identifier into camel case. --
lib/Data/GI/CodeGen/Transfer.hs view
@@ -30,7 +30,6 @@ basicFreeFn (TBasicType TFileName) = Just "freeMem" basicFreeFn (TBasicType _) = Nothing basicFreeFn (TInterface _) = Nothing-basicFreeFn (TCArray False (-1) (-1) _) = Nothing -- Just passing it along basicFreeFn (TCArray{}) = Just "freeMem" basicFreeFn (TGArray _) = Just "unrefGArray" basicFreeFn (TPtrArray _) = Just "unrefPtrArray"@@ -94,9 +93,6 @@                                  return Nothing                           else return Nothing     _ -> return Nothing--- Arrays without length info are just passed along, we do not need to--- free them.-basicFreeFnOnError (TCArray False (-1) (-1) _) _ = return Nothing basicFreeFnOnError (TCArray{}) _ = return $ Just "freeMem" basicFreeFnOnError (TGArray _) _ = return $ Just "unrefGArray" basicFreeFnOnError (TPtrArray _) _ = return $ Just "unrefPtrArray"
lib/Data/GI/GIR/Callback.hs view
@@ -12,6 +12,7 @@  data Callback = Callback { cbCallable :: Callable                          , cbCType    :: Maybe Text+                         , cbDocumentation :: Documentation                          }     deriving Show @@ -20,5 +21,7 @@   name <- parseName   callable <- parseCallable   ctype <- queryCType+  doc <- parseDocumentation   return (name, Callback { cbCallable = callable-                         , cbCType = ctype })+                         , cbCType = ctype+                         , cbDocumentation = doc })
lib/Data/GI/GIR/Field.hs view
@@ -22,6 +22,7 @@       fieldCallback :: Maybe Callback,       fieldOffset :: Int,       fieldFlags :: [FieldInfoFlag],+      fieldDocumentation :: Documentation,       fieldDeprecated :: Maybe DeprecationInfo }     deriving Show @@ -42,6 +43,7 @@              <> if writable then [FieldIsWritable] else []   introspectable <- optionalAttr "introspectable" True parseBool   private <- optionalAttr "private" False parseBool+  doc <- parseDocumentation   (t, isPtr, callback) <-       if introspectable       then do@@ -76,6 +78,7 @@              , fieldCallback = callback              , fieldOffset = error ("unfixed field offset " ++ show name)              , fieldFlags = flags+             , fieldDocumentation = doc              , fieldDeprecated = deprecated           } 
lib/Data/GI/GIR/Property.hs view
@@ -25,6 +25,7 @@         propReadNullable :: Maybe Bool,         propWriteNullable :: Maybe Bool,         propTransfer :: Transfer,+        propDoc :: Documentation,         propDeprecated :: Maybe DeprecationInfo     } deriving (Show, Eq) @@ -42,12 +43,14 @@               <> (if writable then [PropertyWritable] else [])               <> (if construct then [PropertyConstruct] else [])               <> (if constructOnly then [PropertyConstructOnly] else [])+  doc <- parseDocumentation   return $ Property {                   propName = name                 , propType = t                 , propFlags = flags                 , propTransfer = transfer                 , propDeprecated = deprecated+                , propDoc = doc                 -- No support in the GIR for nullability info                 , propReadNullable = Nothing                 , propWriteNullable = Nothing
lib/Data/GI/GIR/Signal.hs view
@@ -11,7 +11,8 @@ data Signal = Signal {         sigName :: Text,         sigCallable :: Callable,-        sigDeprecated :: Maybe DeprecationInfo+        sigDeprecated :: Maybe DeprecationInfo,+        sigDoc :: Documentation     } deriving (Show, Eq)  parseSignal :: Parser Signal@@ -19,8 +20,10 @@   n <- getAttr "name"   deprecated <- parseDeprecation   callable <- parseCallable+  doc <- parseDocumentation   return $ Signal {                 sigName = n               , sigCallable = callable               , sigDeprecated = deprecated+              , sigDoc = doc               }