Skip to content

Commit 19dad20

Browse files
committed
hslua-packaging: calling a doc pushes a Lua table
Provide pure Lua access to documentation object by making the documentation objects callable. The objects return a structured table representation of the documentation when called.
1 parent bae84d5 commit 19dad20

File tree

2 files changed

+95
-7
lines changed

2 files changed

+95
-7
lines changed

hslua-packaging/src/HsLua/Packaging/Documentation.hs

Lines changed: 87 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ module HsLua.Packaging.Documentation
3030
, generateTypeDocumentation
3131
) where
3232

33-
import Control.Monad (void)
33+
import Data.Version (showVersion)
3434
import HsLua.Core as Lua
3535
import HsLua.Marshalling
3636
import HsLua.ObjectOrientation (UDTypeGeneric (..))
3737
import HsLua.Packaging.Types
38+
import HsLua.Typing (pushTypeSpec)
3839
import qualified Data.Map.Strict as Map
3940
import qualified Data.Text as T
4041
import qualified HsLua.Core.Utf8 as Utf8
@@ -155,18 +156,30 @@ peekDocumentationObject idx = do
155156
Just doc -> pure doc
156157

157158
-- | Pushes a 'DocumentationObject' to the Lua stack.
158-
pushDocumentationObject :: Pusher e DocumentationObject
159+
pushDocumentationObject :: LuaError e => Pusher e DocumentationObject
159160
pushDocumentationObject obj = do
160161
newhsuserdatauv obj 0
161162
pushDocumentationObjectMT
162163
setmetatable (nth 2)
163164

164165
-- | Pushes the metatable for documentation objects.
165-
pushDocumentationObjectMT :: LuaE e ()
166-
pushDocumentationObjectMT = void $ newudmetatable documentationObjectName
166+
pushDocumentationObjectMT :: LuaError e => LuaE e ()
167+
pushDocumentationObjectMT = newudmetatable documentationObjectName >>= \case
168+
False -> return ()
169+
True -> do -- newly created metatable at the top of the stack
170+
-- Allow to "call" the documentation object, in which case it should
171+
-- return a Lua table that has all the relevant info.
172+
pushHaskellFunction $ do
173+
-- object is the first argument
174+
forcePeek (peekDocumentationObject (nthBottom 1)) >>= \case
175+
DocObjectFunction fn -> pushFunctionDocAsTable fn
176+
DocObjectModule mdl -> pushModuleDocAsTable mdl
177+
DocObjectType ty -> pushTypeDocAsTable ty
178+
return (NumResults 1)
179+
setfield (nth 2) "__call"
167180

168181
-- | Pushes the documentation of a module as userdata.
169-
pushModuleDoc :: Pusher e ModuleDoc
182+
pushModuleDoc :: LuaError e => Pusher e ModuleDoc
170183
pushModuleDoc = pushDocumentationObject . DocObjectModule
171184

172185
-- | Retrieves a module documentation object from the Lua stack.
@@ -176,7 +189,7 @@ peekModuleDoc idx = peekDocumentationObject idx >>= \case
176189
_ -> failPeek "Not a module documentation object"
177190

178191
-- | Pushes function documentation as userdata.
179-
pushFunctionDoc :: Pusher e FunctionDoc
192+
pushFunctionDoc :: LuaError e => Pusher e FunctionDoc
180193
pushFunctionDoc = pushDocumentationObject . DocObjectFunction
181194

182195
-- | Retrieve function documentation from the Lua stack.
@@ -186,11 +199,78 @@ peekFunctionDoc idx = peekDocumentationObject idx >>= \case
186199
_ -> failPeek "Not a function documentation"
187200

188201
-- | Pushes documentation type documentation as userdata.
189-
pushTypeDoc :: Pusher e FunctionDoc
202+
pushTypeDoc :: LuaError e => Pusher e FunctionDoc
190203
pushTypeDoc = pushDocumentationObject . DocObjectFunction
191204

192205
-- | Retrieve function documentation from the Lua stack.
193206
peekTypeDoc :: Peeker e TypeDoc
194207
peekTypeDoc idx = peekDocumentationObject idx >>= \case
195208
DocObjectType tydoc -> pure tydoc
196209
_ -> failPeek "Not a type documentation"
210+
211+
212+
-- | Pushes the documentation of a module as a table with string fields
213+
-- @name@ and @description@.
214+
pushModuleDocAsTable :: LuaError e => Pusher e ModuleDoc
215+
pushModuleDocAsTable = pushAsTable
216+
[ ("name", pushText . moduleDocName)
217+
, ("description", pushText . moduleDocDescription)
218+
, ("fields", pushList pushFieldDocAsTable . moduleDocFields)
219+
, ("functions", pushList pushFunctionDocAsTable . moduleDocFunctions)
220+
, ("types", pushList pushTypeDocAsTable . moduleDocTypes)
221+
]
222+
223+
-- | Pushes the documentation of a field as a table with string fields
224+
-- @name@ and @description@.
225+
pushFieldDocAsTable :: LuaError e => Pusher e FieldDoc
226+
pushFieldDocAsTable = pushAsTable
227+
[ ("name", pushText . fieldDocName)
228+
, ("type", pushTypeSpec . fieldDocType)
229+
, ("description", pushText . fieldDocDescription)
230+
]
231+
232+
-- | Pushes the documentation of a function as a table with string
233+
-- fields, @name@, @description@, and @since@, sequence field
234+
-- @parameters@, and sequence or string field @results@.
235+
pushFunctionDocAsTable :: LuaError e => Pusher e FunctionDoc
236+
pushFunctionDocAsTable = pushAsTable
237+
[ ("name", pushText . funDocName)
238+
, ("description", pushText . funDocDescription)
239+
, ("parameters", pushList pushParameterDocAsTable . funDocParameters)
240+
, ("results", pushResultsDoc . funDocResults)
241+
, ("since", maybe pushnil (pushString . showVersion) . funDocSince)
242+
]
243+
244+
-- | Pushes the documentation of a parameter as a table with boolean
245+
-- field @optional@ and string fields @name@, @type@, and @description@.
246+
pushParameterDocAsTable :: LuaError e => Pusher e ParameterDoc
247+
pushParameterDocAsTable = pushAsTable
248+
[ ("name", pushText . parameterName)
249+
, ("type", pushTypeSpec . parameterType)
250+
, ("description", pushText . parameterDescription)
251+
, ("optional", pushBool . parameterIsOptional)
252+
]
253+
254+
-- | Pushes a the documentation for a function's return values as either
255+
-- a simple string, or as a sequence of tables with @type@ and
256+
-- @description@ fields.
257+
pushResultsDoc :: LuaError e => Pusher e ResultsDoc
258+
pushResultsDoc = \case
259+
ResultsDocMult desc -> pushText desc
260+
ResultsDocList resultDocs -> pushList pushResultValueDoc resultDocs
261+
262+
-- | Pushes the documentation of a single result value as a table with
263+
-- fields @type@ and @description@.
264+
pushResultValueDoc :: LuaError e => Pusher e ResultValueDoc
265+
pushResultValueDoc = pushAsTable
266+
[ ("type", pushTypeSpec . resultValueType)
267+
, ("description", pushText . resultValueDescription)
268+
]
269+
270+
-- | Pushes the documentation of a UDType as a Lua table.
271+
pushTypeDocAsTable :: LuaError e => Pusher e TypeDoc
272+
pushTypeDocAsTable = pushAsTable
273+
[ ("name", pushText . typeDocName)
274+
, ("description", pushText . typeDocDescription)
275+
, ("methods", pushList pushFunctionDoc . typeDocMethods)
276+
]

hslua-packaging/test/HsLua/Packaging/DocumentationTests.hs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ tests = testGroup "Documentation"
3333
Lua.TypeNil `shouldBeResultOf` do
3434
OK <- Lua.dostring "return function () return 1 end"
3535
getdocumentation top
36+
37+
, "Calling the doc object returns a table" =:
38+
Lua.TypeTable `shouldBeResultOf` do
39+
pushDocumentedFunction factorial
40+
_ <- getdocumentation top
41+
Lua.pushvalue top
42+
Lua.call 1 1
43+
Lua.ltype top
3644
]
3745
]
3846

0 commit comments

Comments
 (0)