haskellhaddockhsc2hs

How to make haddock documentation for hsc2hs enum members


I'm using hsc2hs to import a bunch of enum values from C header. My code (simplified) looks like this:

-- | newtype wrapper around Windows SDK SE_OBJECT_TYPE enumeration
newtype SecurityObjectType = SecurityObjectType BYTE
#{enum SecurityObjectType, SecurityObjectType
 , securityObjectUnknown            = SE_UNKNOWN_OBJECT_TYPE
 , securityObjectFile               = SE_FILE_OBJECT
 }

When I run cabal haddock on my project, it creates empty documentation blocks for declarations securityObjectUnknown and securityObjectFile of type SecurityObjectType. Now I would like to have documentation for these. Simply using haddock style comments like

-- | newtype wrapper around Windows SDK SE_OBJECT_TYPE enumeration
newtype SecurityObjectType = SecurityObjectType BYTE
#{enum SecurityObjectType, SecurityObjectType
 -- | Unknown object type
 , securityObjectUnknown            = SE_UNKNOWN_OBJECT_TYPE
 -- | Indicates a file or directory. The name string that identifies a file
 -- or directory object can be in one of the following formats:
 --  * A relative path, such as FileName.dat or ..\FileName
 --  * An absolute path, such as FileName.dat, C:\DirectoryName\FileName.dat,
 --    or G:\RemoteDirectoryName\FileName.dat.
 --  * A UNC name, such as \\ComputerName\ShareName\FileName.dat.
 , securityObjectFile               = SE_FILE_OBJECT
 }

interferes with hsc2hs and makes build fail. But I want to have these declarations documented. How could I do that?

UPD: Here is an error message generated during build if I have comments:

Preprocessing library Win32-security-0.1...                                                                                     
SecurityInfo.hsc: In function 'main':                                                                                           
SecurityInfo.hsc:47:5: error: lvalue required as decrement operand                                                              
SecurityInfo.hsc:47:5: error: 'Indicates' undeclared (first use in this function)                                               
SecurityInfo.hsc:47:5: note: each undeclared identifier is reported only once for each function it appears in                   
SecurityInfo.hsc:47:5: error: expected ')' before 'a'                                                                           
SecurityInfo.hsc:47:5: error: lvalue required as decrement operand                                                              
SecurityInfo.hsc:47:5: error: expected ')' before 'a'                                                                           
SecurityInfo.hsc:47:5: error: lvalue required as decrement operand                                                              
SecurityInfo.hsc:47:5: error: expected ')' before 'a'                                                                           
SecurityInfo.hsc:55:20: warning: missing terminating " character                                                                
SecurityInfo.hsc:56:24: warning: missing terminating " character                                                                
SecurityInfo.hsc:66:20: warning: missing terminating " character                                                                
SecurityInfo.hsc:67:18: warning: missing terminating " character                                                                
SecurityInfo.hsc:71:20: warning: missing terminating " character                                                                
SecurityInfo.hsc:72:2: warning: missing terminating " character                                                                 
SecurityInfo.hsc:237:0: error: unterminated argument list invoking macro "hsc_enum"                                             
SecurityInfo.hsc:53:5: error: 'hsc_enum' undeclared (first use in this function)                                                
SecurityInfo.hsc:53:5: error: expected ';' at end of input                                                                      
SecurityInfo.hsc:53:5: error: expected declaration or statement at end of input                                                 
compiling dist\build\System\Win32\Security\SecurityInfo_hsc_make.c failed (exit code 1)                 

Line numbers don't actually match because the example is simplified, but line 47 in error output correspons to an -- | Unknown object type line.

Digging into generated SecurityInfo_hsc_make.c file clearly shows a problem (here is a fragment):

#line 47 "SecurityInfo.hsc"
    hsc_enum (SecurityObjectType,  SecurityObjectType
 -- | Unknown object type
 , hsc_printf ("%s", "securityObjectUnknown            "),  SE_UNKNOWN_OBJECT_TYPE
 -- | Indicates a file or directory. The name string that identifies a file
 -- or directory object can be in one of the following formats:
 --  * A relative path);
    hsc_enum (SecurityObjectType,  SecurityObjectType
 -- | Unknown object type
 , hsc_haskellize ("such as FileName.dat or ..\FileName
 --  * An absolute path"), such as FileName.dat or ..\FileName
 --  * An absolute path);
    hsc_enum (SecurityObjectType,  SecurityObjectType
 -- | Unknown object type
 , hsc_haskellize ("such as FileName.dat"), such as FileName.dat);
    hsc_enum (SecurityObjectType,  SecurityObjectType
 -- | Unknown object type

Haskell comments are simply inserted into a generated C file, which obviously violates C syntax rules. What I wanted is to get these comments propagates to an auto-generated .hs file.


Solution

  • As far as I can tell, you have to define each value one at a time using #const instead of defining them all at once with #enum if you want to add documentation.

    -- | Unknown object type
    securityObjectUnknown :: SecurityObjectType
    securityObjectUnknown = SecurityObjectType #const SE_UNKNOWN_OBJECT_TYPE
    
    -- | Indicates a file or directory. The name string that identifies a file
    -- or directory object can be in one of the following formats:
    --  * A relative path, such as FileName.dat or ..\FileName
    --  * An absolute path, such as FileName.dat, C:\DirectoryName\FileName.dat,
    --    or G:\RemoteDirectoryName\FileName.dat.
    --  * A UNC name, such as \\ComputerName\ShareName\FileName.dat.
    securityObjectFile :: SecurityObjectType
    securityObjectFile = SecurityObjectType #const SE_FILE_OBJECT