Special ALIASES
It was one of the main goals to document the Delphi code like C/C++ code including the declaration of the documented entity with a minimum overhead. This is done by inserting part of the Delphi code via Doxygen's \include
/ \dontinclude
mechanism and requires also some conventions on writing the code - s. description on each command in chapter Main Commands .
The set of ALIASES
mainly consists of 2 groups each with just a couple commands:
- Main Commands : These commands are sufficient to document the code.
The commands start a documentation block for the intended entity; afterwards nearly all "normal" Doxygen special commands can be used!
The Main Commands are composed of
- Low level Commands : These commands may not explicitly used for commenting; mainly they are intended to just simplify (and unify) the internal definition of the Main Commands , but also are useful for special purposes or for composing own commands.
Additionally there are commands for extracting C/C++ code from Delpi's generated .hpp files:
And at last some things can documented out of the box:
Most commands have one or more arguments. Each argument has a certain range:
- {curly} braces are used to enclose the arguments of an alias!
- If <sharp> braces are used the argument is a single word.
- If (round) braces are used the argument may consist of several words, but "," (comma) isn't allowed, cause it's the argument delimiter for aliases!
- If, in addition to the above argument specifiers, [square] brackets are used the argument is optional.
- Note
- Be aware that the Doxygen documentation sections must be surrounded with a
\endcond
.. \cond
pair; for better readability this is sometimes omitted in the following examples.
...Delphi code
//! @endcond re-enable Doxygen parsing!
//! ...Doxygen documentation
//! @cond disable Doxygen parsing again
...Delphi code
C/C++ like documentation
Amazingly Doxygen is able to interpret Delphi some entities anyway like C/C++.
This is described in the following chapters.
const Declarations
Simple CONST's are obviously interpreted as variables without type. So they can documented in pure Doxygen-C/C++ manner, s. following examples, found in Example_CONST.pas:
- Example:
33 //! @brief CONSTs may be documented directly in both ways:
35 //! number of ASCII-ctrlchars: Comment before... \n
37 ASCIICtrlCnt = 32; //!< ...and after the statement
39 ASCIICharBitCnt = 8; //!< No of Bits for ASCII chars
40 ASCIICharsCnt = 1 shl ASCIICharBitCnt; //!< whole number of ASCII chars
41 CONST ASCIICharsPrintable = ASCIICharsCnt - ASCIICtrlCnt; //!< number of printable ASCII chars
They also can be put into a member group as shown in this example:
- Example:
48 //! @Name{ASCII_Codes,ASCII-Konstanten}
49 //! ASCII-Ctrl-Codes, documented as member group
52 SOH = #$01; //!< ^A: Start of Header
53 STX = #$02; //!< ^B: Start of Text
54 ETX = #$03; //!< ^C: End of Text
56 EOT = #$04; //!< ^D: End of transmission
57 ENQ = #$05; //!< ^E: Enquiry
58 ACK = #$06; //!< ^F: Acknowledge
59 BEL = #$07; //!< ^G: Bell
61 BS = #$08; //!< ^H: Backspace
62 HT = #$09; TAB = #$09; //!< ^I: Horizontal Tab
63 LF = #$0A; //!< ^J: Line feed
64 VT = #$0B; //!< ^K: Vertical Tab
66 FF = #$0C; //!< ^L: Form feed
67 CR = #$0D; RET = #$0D; //!< ^M: Carriage return
68 SO = #$0E; //!< ^N: Shift out
69 SI = #$0F; //!< ^O: Shift in
71 DLE = #$10; //!< ^P: Data link esacpe
77 NAK = #$15; //!< ^U: Negative acknowledge
78 SYN = #$16; //!< ^V: Synchronous idle
79 ETB = #$17; XON = #$17; //!< ^W: End of transmission block
81 CAN = #$18; //!< ^X: Cancel
82 EM = #$19; XOFF = #$19; //!< ^Y: End of medium
83 SUB = #$1A; //!< ^Z: Substitute
84 ESC = #$1B; //!< ^[: Escape
86 FS = #$1C; //!< ^\\: File separator
87 GS = #$1D; //!< ^]: Group separator
88 RS = #$1E; //!< ^^: Record separator
89 US = #$1F; //!< ^_: Unit separator
91 // -----------------------------------------------------------------------------
- Note
- Since Doxygen interprets this statements as C-variables the documentation appears in Doxygen's Variables section
- Attention
- Be aware that this behavior is restricted to pure Delphi CONSTs (which are semantically similar to C/C++ #defines)! For commenting Delphi's typed CONSTs, which are syntactically similar to (typed) VARs (and which are more closely to C/C++ const) use special ALIAS \DConst.
unit Statement
A unit statement appears to C/C++ and therefore to Doxygen as declaration of a variable <unitname> of type unit. This indeed is not very useful - but a Doxygen PREDEFINED macro
PREDEFINED += unit="typedef struct {}"
can convert this into a struct type; this afterwards is used to gather all the unit's plain function declaration - to bypass Doxygen's restriction that all plain function have to be declared completely, but not member functions, s. \DFunc and \DProc.
Embedding C/C++ statements
Also for special purposes C/C++ statements may be embedded into the Delphi source code; but keep in mind that this only relates to Doxygen parsing, not for generating C++Builder code by Delphi itself!
This may simply be done by a combination of Delphi and Doxygen comments:
A Delphi block comment pair (* *)
preserves the statements from being parsed by Delphi; inside this Delphi comment block Doxygen parsing is enabled with a //! \endcond .. //! \cond
or a /** \endcond .. \cond */
pair as in the following example:
(* //! \endcond
...C/C++ statements and / or more Doxygen commenting
//! \cond *)
or
(* /** \endcond
...Doxygen commenting
\cond */ *)
- Attention
- Inside the intended Delphi comment block no closing
*)
must appear since Delphi would recognize the end of the block resulting in syntax errors. Using Delphi's (* *)
comment blocks instead of { }
comment blocks is advised since { }
are also part of C/C++ syntax and it is very likely that they are used in C/C++ statements...
Special ALIASES for Delphi
Main Commands
These commands are sufficient for commenting the code; for special purposes or more detailed or more sophisticated documentation s. next chapter .
Each command has hat least two arguments:
- name of the entity to document
- name of the module including this entity, i.e. Delphi source file without extension ".pas"
- Note
- The explicit notation of the module name is the only general overhead
- additional overhead is made for documenting class and struct members: as the documentation is (from Doxygen's point of view) outside the entity's scope, the class / struct name is required to inform Doxygen to which upper scope the documentation belongs.
- Delphi Source files must be available via EXAMPLE_PATH.
The commands start a documentation block for the intended entity; afterwards nearly all "normal" Doxygen special commands can be used!
Only these are used to document the example project:
\DType{<typename>,<modulename>}
Documenting a type.
- Arguments:
- type name
- module name: Delphi source file (without extension ".pas") including the type declaration
- Formatting conventions:
- there must at least one space before the type name
- the "=" sign between typename and type declaration is surrounded with exactly one space before.
-
ALIASES += \
"DType{2}=\typedef \1 ^^ \DDeclHdr{\2,\1} \DTypeDecl{\1}" \
- Example:
25 //! @DType{TASCIICtrls, Example_TYPE}
26 //! @brief enumeration of ASCII-ctrlchars
28 TYPE TASCIICtrls = #$00..#$1F;
- Resulting documentation:
- TASCIICtrls
More Examples s. Example_TYPE.pas.
\DDef{<macro-name>,<modulename>}
Intended to document Delphi CONSTs converted to C/C++ macros: not used since Delphi converts these to C/C++ const's.
Since Delphi's CONSTs are syntactically similar to TYPEs: Equivalent to \DType
\DVar{<variablename>,<modulename>}
Documenting a var, initialized var or typed const
- Arguments:
- variable name
- module name: Delphi source file (without extension ".pas") including the var or const declaration
- Formatting conventions:
- there must at least one space before the <varname>
- the ":" sign follows directly after the <varname> without any space
-
ALIASES += \
"DVar{2}=\var \1 ^^ \DDeclHdr{\2,\1} \DVarDecl{\1}" \
- Example:
31 //! @DVar{ASCIICtrls, Example_VAR}
32 //! variable: set containing ASCII-ctrlchars
34 VAR ASCIICtrls: TASCIICtrlSet;
- Resulting documentation:
- ASCIICtrls
More Examples s. Example_TYPE.pas.
\DConst{<constname>,<modulename>}
Equivalent to \DVar
\DFunc{<functionname>,<modulename>}
Documenting a function
- Arguments:
- function name
- module name: Delphi source file (without extension ".pas") including the function declaration
- Note
- Since for plain functions Doxygen requires a complete C/C++ declaration (in opposite to struct or class methods where the method name is sufficient!) the procedure is treated as a member of the unit struct ( s. unit Statement ).
- Formatting conventions:
- there must at least one space before the <function_methodname> name
- the opening "(" of the parameter list follows directly after the function's identifier without any spaces;
- therefore functions with no arguments must have explicitly an empty parameter list "()"
- the ":" sign follows directly after the closing ")" of the parameter list
- the closing ";" sign is at the same line as the closing ":", i.e. "):", function type and ";" are all in the same line.
Note, that the declaration may be written in multiple lines, only the closing "):", function type and ";" must be in a single line.
-
ALIASES += \
"DFunc{2}=\Dfn{\1,\2} ^^ \DDeclHdr{\2,\1} \DFuncDecl{\1}" \
- Example:
54 //! @DFunc{ReplaceFunc,Example_FUNC}
55 //! @brief replaces ASCII-ctrlchars
57 //! @CFunc{ReplaceFunc,Example_FUNC}
59 //! replaces ASCII-ctrlchars with blanks, nothing, name or hex depending
60 //! depending on whether the char is included in the respective ReplaceXxxx set
62 //! @param AString Input string
63 //! @param ReplaceBlanks set with ctrlchars to replace by Spaces
64 //! @param ReplaceNone set with ctrlchars to delete
65 //! @param ReplaceName set with ctrlchars to replace by their names
66 //! @param ReplaceHex set with ctrlchars to replace by their hex representation
67 //! @result AString with replaced ctrlchars
69 //! @note uses typed CONST @ref ASCIINames
71 FUNCTION ReplaceFunc(AString: AnsiString;
72 // TASCIICtrlSets zur Behandlung von Ctrl-Zeichen:
74 CONST ReplaceBlanks, // ...ersetzen durch Blanks
75 ReplaceNone, // ...entfernen
76 ReplaceName, // ...ersetzen durch den Namen
77 ReplaceHex: // ...ersetzen durch Hex
78 TASCIICtrlSet): AnsiString;
- Resulting documentation:
- ReplaceFunc
More Examples s. Example_FUNC.pas.
\DProc{<procedurename>,<modulename>}
Documenting a procedure
- Arguments:
- procedure name
- module name: Delphi source file (without extension ".pas") including the procedure declaration
- Note
- Since for plain functions Doxygen requires a complete C/C++ declaration (in opposite to struct or class methods where the method name is sufficient!) the procedure is treated as member of the unit struct ( s. unit Statement ).
- Formatting conventions:
- there must at least one space before the <procedure_methodname> name
- the opening "(" of the parameter list follows directly after the procedure's identifier without any spaces
- therefore procedures with no arguments must have explicitly an empty parameter list "()"
- the ";" sign follows directly after the closing ")" of the parameter list
Note, that the declaration may be written in multiple lines.
-
ALIASES += \
"DProc{2}=\Dfn{\1,\2} ^^ \DDeclHdr{\2,\1} \DProcDecl{\1}" \
- Example:
27 //! @DProc{ReplaceProc,Example_FUNC}
28 //! @brief replaces ASCII-ctrlchars
30 //! @CProc{ReplaceProc,Example_FUNC}
32 //! replaces ASCII-ctrlchars with blanks, nothing, name or hex depending
33 //! depending on whether the char is included in the respective ReplaceXxxx set
34 //! @param[in,out] AString Input string / Output ttring with replaced ctrlchars
35 //! @param ReplaceNone set with ctrlchars to delete
36 //! @param ReplaceName set with ctrlchars to replace by their names
37 //! @param ReplaceHex set with ctrlchars to replace by their hex representation
39 //! @note uses typed CONST @ref ASCIINames
41 PROCEDURE ReplaceProc(VAR AString: AnsiString;
42 // TASCIICtrlSets zur Behandlung von Ctrl-Zeichen:
44 CONST ReplaceBlanks, // ...ersetzen durch Blanks
45 ReplaceNone, // ...entfernen
46 ReplaceName, // ...ersetzen durch den Namen
47 ReplaceHex: // ...ersetzen durch Hex
- Resulting documentation:
- ReplaceProc
More Examples s. Example_FUNC.pas.
\DEnumType{<enum-typename>,<modulename>}
Documenting an enumeration type.
- Arguments:
- enumeration type name
- module name: Delphi source file (without extension ".pas") including the type declaration
- Formatting conventions:
- there must at least one space before the type name
- the "=" sign between typename and initial "(" is surrounded with exactly one space before.
- the ";" sign follows directly after the closing ")" of the enumeration list.
-
ALIASES += \
"DEnumType{2}=\enum \1 ^^ \DDeclHdr{\2,\1} \DEnumTypeDecl{\1}" \
- Example:
48 //! @DEnum{TASCIIEnum, Example_TYPE}
49 //! @brief Enumeraton of all ASCII-ctrlchars
51 TYPE TASCIIEnum = (NUL, SOH, STX, ETX,
- Resulting documentation:
- TASCIIEnum
More Examples s. Example_TYPE.pas.
\DEnumVar{<enum-varname>,<modulename>}
Documenting an enumeration variable.
- Arguments:
- enumeration variable name
- module name: Delphi source file (without extension ".pas") including the variable declaration
- Formatting conventions:
- there must at least one space before the type name
- the ":" sign follows directly after the <enum-varname> without any space
- the ";" sign follows directly after the closing ")" of the enumeration list.
-
ALIASES += \
"DEnumVar{2}=\var \1 ^^ \DDeclHdr{\2,\1} \DEnumVarDecl{\1}" \
- Example:
92 //! @DEnumVar{ASCII_Enum, Example_VAR}
93 //! @brief Enumeration of all ASCII-ctrlchars
95 VAR ASCII_Enum: (NUL, SOH, STX, ETX,
- Resulting documentation:
- ASCII_Enum
More Examples s. Example_TYPE.pas.
\DEnum{<enum-name>,<modulename>}
Equivalent to \DEnumType
\DRecordType{<record_typename>,<modulename>}
Documenting a record type
- Arguments:
- record type name
- module name: Delphi source file (without extension ".pas") including the type declaration
- Formatting conventions:
- there must at least one space before the type name
- the "=" sign between typename and type declaration is surrounded with exactly one space before.
- after the closing "end;" keyword there follows a line comment with the <record_typename>; the line comment " // " is surrounded with exactly one space before and behind.
- anonymous Delphi record fields are not sufficient for Doxygen documentation
-
ALIASES += \
"DRecordType{2}=\Dstruct{\1} ^^ \DDeclHdr{\2,\1} \DCompTypeDecl{\1}" \
- Example:
65 //! @DRecordType{TASCIICtrlChar,Example_TYPE}
66 //! @brief type definiton: Record to describe an ASCII ctrlchar
68 //! @DRecordField{TASCIICtrlChar,name,Example_TYPE}
69 //! @brief name of the ASCII-ctrlchar
71 //! @DRecordField{TASCIICtrlChar,c,Example_TYPE}
72 //! @brief the ASCII-ctrlchar interpreted as AnsiChar
75 TYPE TASCIICtrlChar = RECORD
76 c: AnsiChar; // ASCII Ctrl character
77 name: AnsiString; // name of the Character
78 END; // TASCIICtrlChar
- Resulting documentation:
- TASCIICtrlChar
More Examples s. Example_TYPE.pas.
\DRecordVar{<record_varname>,<modulename>}
Documenting a record type
- Arguments:
- record variable name
- module name: Delphi source file (without extension ".pas") including the type declaration
- Formatting conventions:
- there must at least one space before the type name
- the ":" sign follows directly after the <record_varname> without any space
- after the closing "end;" keyword there follows a line comment with the <record_typename>; the line comment " // " is surrounded with exactly one space before and behind.
- anonymous Delphi record fields are not sufficient for Doxygen documentation
-
ALIASES += \
"DRecordVar{2}=\var \1 ^^ \DDeclHdr{\2,\1} \DCompVarDecl{\1}" \
- Example:
65 //! @DRecordType{TASCIICtrlChar,Example_TYPE}
66 //! @brief type definiton: Record to describe an ASCII ctrlchar
68 //! @DRecordField{TASCIICtrlChar,name,Example_TYPE}
69 //! @brief name of the ASCII-ctrlchar
71 //! @DRecordField{TASCIICtrlChar,c,Example_TYPE}
72 //! @brief the ASCII-ctrlchar interpreted as AnsiChar
75 TYPE TASCIICtrlChar = RECORD
76 c: AnsiChar; // ASCII Ctrl character
77 name: AnsiString; // name of the Character
78 END; // TASCIICtrlChar
- Resulting documentation:
- TASCIICtrlChar
More Examples s. Example_TYPE.pas.
\DRecordField{<record_fieldname>,<modulename>}
Documenting a record field
- Arguments:
- record field name
- module name: Delphi source file (without extension ".pas") including the record type declaration
- Formatting conventions:
- there must at least one space before the record field name
- the ":" sign follows directly after the <record_fieldname> without any space
-
ALIASES += \
"DRecordField{3}=\Dmember{\1,\2} ^^ \DDeclHdr{\3,\1,\2} \DVarDecl{\2}" \
s. DRecord example above
\DRecord{<record_typename>,<modulename>}
Equivalent to \DRecordType
\DClassType{<classname>,<modulename>}
Documenting a class
- Arguments:
- class name
- module name: Delphi source file (without extension ".pas") including the class declaration
- Formatting conventions:
- there must at least one space before the class name
- the "=" sign between class name and type declaration is surrounded with exactly one space before.
- the "class" keyword is all lowercase and followed directly by the opening round brace "("
- after the closing "end;" keyword there follows a line comment with the <classname>; the line comment " // " is surrounded with exactly one space before and behind.
-
ALIASES += \
"DClassType{2}=\Dclass{\1} ^^ \DDeclHdr{\2,\1} \DCompTypeDecl{\1}" \
- Example:
23 //! @DClass{TClass1,Example_CLASS}
26 //! Basic class without an ancestor (--> defaults to TObject)
32 destructor Destroy(); override;
35 //! @var TClass1::Field1
36 //! @brief TClass 1 / Field 1
41 //! @fn TClass1::Func1
42 //! @brief TClass 1 / Func 1
44 FUNCTION Func1(): INTEGER;
47 //! @fn TClass1::Proc1
48 //! @brief TClass 1 / Proc 1
50 PROCEDURE Proc1(AField: INTEGER);
53 //! @property TClass1::Prop1
54 //! @brief property TClass 1 / Prop 1
56 property Prop1: INTEGER read Field1 write Field1; // Prop1
- Resulting documentation:
- TClass1
More Examples s. Example_CLASS.pas.
\DClass{<classname>,<modulename>}
Equivalent to \DClassType
\DClassField{<classname>,<class_variablename>,<modulename>}
Documenting a class variable
- Arguments:
- class name
- class variable name
- module name: Delphi source file (without extension ".pas") including the class declaration
- Formatting conventions:
- there must at least one space before the var name
- the ":" sign follows directly after the var (without any space)
-
ALIASES += \
"DClassField{3}=\Dmember{\1,\2} ^^ \DDeclHdr{\3,\1,\2} \DVarDecl{\2}" \
- Example:
71 //! @DClassField{TClass2,Field2,Example_CLASS}
72 //! @brief TClass 2 / Field 2
- Resulting documentation:
- TClass2::Field2
More Examples s. Example_CLASS.pas.
\DClassProp{<classname>,<class_propertyname>,<modulename>}
Documenting a class variable
- Arguments:
- class name
- class property name
- module name: Delphi source file (without extension ".pas") including the class declaration
- Formatting conventions:
- there must at least one space before the property name
- the ":" sign follows directly after the property (without any space)
- after the closing ";" there follows a line comment with the <propertyname>; the line comment " // " is surrounded with exactly one space before and behind.
-
ALIASES += \
"DClassProp{3}=\Dproperty{\1,\2} ^^ \DDeclHdr{\3,\1,\2} \DCompVarDecl{\2}" \
- Example:
95 //! @DClassProp{TClass2,Prop2,Example_CLASS}
96 //! @brief property TClass 2 / Prop 2
98 property Prop2: INTEGER read Field2 write Field2; // Prop2
- Resulting documentation:
- TClass2::Prop2
More Examples s. Example_CLASS.pas.
\DClassFunc{<classname>,<function_methodname>,<modulename>}
Documenting a class function
- Arguments:
- class name
- class function name
- module name: Delphi source file (without extension ".pas") including the class declaration
- Formatting conventions:
- there must at least one space before the <function_methodname> name
- function with no arguments must have explicitly an empty parameter list "()"
- the ":" sign follows directly after the closing ")" of the parameter list
- the closing ";" sign is at the same line as the closing ":", i.e. "):", function type and ";" are all in the same line.
Note, that the declaration may be written in multiple lines, only the closing "):", function type and ";" must be in a single line.
-
ALIASES += \
"DClassType{2}=\Dclass{\1} ^^ \DDeclHdr{\2,\1} \DCompTypeDecl{\1}" \
- Example:
79 //! @DClassFunc{TClass2,Func2,Example_CLASS}
80 //! @brief TClass 2 / Func 2
82 FUNCTION Func2(): INTEGER;
- Resulting documentation:
- TClass2::Func2
More Examples s. Example_CLASS.pas.
\DClassProc{<classname>,<procedure_methodname>,<modulename>)}
Documenting a class procedure
- Arguments:
- class name
- class procedure name
- module name: Delphi source file (without extension ".pas") including the class declaration
- Formatting conventions:
- there must at least one space before the <procedure_methodname> name
- the "(" sign follows directly after the <procedure_methodname> name without any space
- procedures with no arguments must have explicitly an empty parameter list "()"
- the ";" sign follows directly after the closing ")" of the parameter list
Note, that the declaration may be written in multiple lines.
-
ALIASES += \
"DClassProc{3}=\Dmethod{\1,\2} ^^ \DDeclHdr{\3,\1,\2} \DProcDecl{\2}" \
- Example:
87 //! @DClassProc{TClass2,Proc2,Example_CLASS}
88 //! @brief TClass2 / Proc 2
- Resulting documentation:
- TClass2::Proc2
More Examples s. Example_CLASS.pas.
\DClassCtor{<classname>,<constructor_methodname>,<modulename>)}
Class constructor declaration: equivalent to \DClassProc
\DClassDtor{<classname>,<destructor_methodname>,<modulename>)}
Class destructor declaration: equivalent to \DClassProc
\DUnionType{<union_typename>,<modulename>}
Since anonymous Delphi record fields are not sufficient for Doxygen documentation these are treated as equivalent to \DRecordType
\DUnionVar{<union_varname>,<modulename>}
Since anonymous Delphi record fields are not sufficient for Doxygen documentation these are treated as equivalent to \DRecordVar
\DUnionField{<union_fieldname>,<modulename>}
Since anonymous Delphi record fields are not sufficient for Doxygen documentation these are treated as equivalent to \DRecordField
\DUnion{<union-name>,<modulename>}
Since anonymous Delphi record fields are not sufficient for Doxygen documentation these are treated as equivalent to to \DRecord
Low level Commands
The Main commands are sufficient for all documentation purposes. As described above each alias consists of several Doxygen special commands. To simplify/unify the alias definition they are composed on a couple of lower level aliases which can be used to do more sophisticated documentation and/or to create your own aliases.
Each of the above aliases consists of 3 parts:
- <\entity>
C/C++ entity name (i.e. \def, \typedef, \fn, \var, \property, \struct, \enum, \union and \class) to start the documentation section
- \DeclHdr{..}
displays the headline, loads the Delphi module and skips to the entity declaration marked by the occurrence as first argument of the alias.
- \D<Entity>Decl{..}
Finally inserts the Delphi code snippet for the desired entity
Common usable aliases; may also used for other purposes as documenting Delphi code:
Additionally defined further aliases for generic entities to simplify some conventions to be met:
Insert Delphi source code snippets into the documentation; these aliases also define the coding conventions:
- Note
- If you prefer other conventions you may want to change these aliases.
— Helper commands —
Common usable aliases; may also used for other purposes as documenting Delphi code.
\Snippet{[<filename>,](first line pattern),(last line pattern)}
Helper command like the original \snippet command, but without any needing to define a blockid:
This version optionally loads a file <filenam>, skips to the (first line pattern) and displays all stuff until the (last line pattern) is reached (which is displayed as last line).
- Note
- If (first line pattern) and (last line pattern) are on the same line only this single line is displayed!
-
ALIASES += \
"Snippet{2}=\skip \1 ^^ \until \2 ^^ " \
"Snippet{3}=\dontinclude \1 ^^ \Snippet{\2,\3}" \
\SkipSnippet{(first line pattern),(last line pattern)}
Helper command to
- skip a snippet of code up to (first line pattern)
- skip to (last line pattern)
- display this last line of this snippet.
- Note
- If (first line pattern) and (last line pattern) are on the same line only this single line is displayed!
-
ALIASES += \
"SkipSnippet{2}=\skip \1 ^^ \skipline \2 ^^ " \
\SkipArg{[<compoundname>,]<entityname>}
Helper command:
- Arguments:
- compound name: name of the record or class this entity belongs
- entity name: Delphi entity to document
Skips to the occurrence of the entity as first argument or the compound and entity name as first and second argument of an alias (i.e. [<compoundname>,]<entityname>
preceded by "{"
).
-
ALIASES += \
"SkipArg{1}=\skip {\1 ^^ " \
"SkipArg{2}=\skip {\1,\2 ^^ " \
\InclPas{<modulename>}
Helper command:
- Arguments:
- module name: Delphi source file (without extension ".pas")
Sets the Delphi source filename with ".pas".
-
ALIASES += \
"InclPas{1}=\dontinclude \1.pas ^^ " \
\DHeader{[<anchor>]}
Helper command:
- optional Arguments:
- anchor
Starts a section with headline "Delphi-Declaration"; optionally places an anchor <anchor>_pas
before the section.
-
ALIASES += \
"DHeader=\par Delphi-Declaration ^^ " \
"DHeader{1}=\anchor \1_pas ^^ \DHeader" \
\DInclDecl{<modulename>,[<compoundname>,]<entityname>}
Helper command:
- Arguments:
- module name: Delphi source file (without extension ".pas") including the entity declaration
- compound name: name of the record or class this entity belongs
- entity name: Delphi entity to document
Sets the Delphi source filename and skips to the occurrence of the entity as first argument or the compound and entity name as first and second argument of an alias (i.e. [<compoundname>,]<entityname>
preceded by "{"
).
-
ALIASES += \
"DInclDecl{2}=\InclPas{\1} \SkipArg{\2}" \
"DInclDecl{3}=\InclPas{\1} \SkipArg{\2,\3}" \
\DDeclHdr{<modulename>,[<compoundname>,]<entityname>}
Helper command:
- Arguments:
- module name: Delphi source file (without extension ".pas") including the entity declaration
- compound name: name of the record or class this entity belongs
- entity name: Delphi entity to document
Starts declaration section with headline "Delphi-Declaration" and sets the Delphi source filename and skips to the entity name declaration by calling special alias \DInclDecl.
Then skips to the occurrence of the entity as first argument or the compound and entity name as first and second argument of an alias (i.e. [<compoundname>,]<entityname>
preceded by "{"
).
-
ALIASES += \
"DDeclHdr{2}=\DHeader{\2} \DInclDecl{\1,\2}" \
"DDeclHdr{3}=\DHeader{\2_\3} \DInclDecl{\1,\2,\3}" \
— Additional entity aliases —
Additional aliases for generic entities to simplify some conventions to be met.
\Dfn{<functionname>,<modulename>}
- Arguments:
- function name: Plain function name
- module name: Delphi source file (without extension ".pas") including the function declaration
Treats / documents a plain function as member of the unit's struct.
-
ALIASES += \
"Dfn{2}=\fn \1 ^^ \memberof \2" \
\Dstruct{<structname>}
- Arguments:
- struct name
Ensures optional parameters of \struct being empty.
-
ALIASES += \
"Dstruct{1}=\struct \1 \"\" \"\" " \
\Dunion{<unionname>}
- Arguments:
- union name
Ensures optional parameters of \union being empty.
-
ALIASES += \
"Dunion{1}=\union \1 \"\" \"\" " \
\Dclass{<classname>}
- Arguments:
- class name
Ensures optional parameters of \class being empty.
-
ALIASES += \
"Dclass{1}=\class \1 \"\" \"\" " \
\Dmember{<compoundname>,<variablename>}
- Arguments:
- compound name: name of a \struct, \union or \class
- variable name: name of a compound's member variable
Treats / documents the variable as member of the compound.
-
ALIASES += \
"Dmember{2}=\var \1::\2" \
\Dmethod{<compoundname>,<functionname>}
- Arguments:
- compound name: name of a \struct, \union or \class
- function name: name of a compound's member method
Treats / documents the function as method of the compound.
-
ALIASES += \
"Dmethod{2}=\fn \1::\2" \
\Dproperty{<compoundname>,<propertyname>}
- Arguments:
- compound name: name of a \struct, \union or \class
- property name: name of a compound's member property
Treats / documents the property as member of the compound.
-
ALIASES += \
"Dproperty{2}=\property \1::\2" \
— Commands to include snippets with Delphi entity declarations —
Each of the following D<Entity>Decl aliases' inserts a Delphi code snippet from a previously set include file for a special entity <entityname>. The limiting line patterns are implicitly defined by <Entity>, s. Summary table.
In the end these aliases define the resp. coding convention that must be met!
\DVarDecl{<entityname>}
Inserts a Delphi code snippet with a variable declaration.
-
ALIASES += \
"DVarDecl{1}=\Snippet{\1:,;}" \
\DTypeDecl{<entityname>}
Inserts a Delphi code snippet with a variable declaration.
-
ALIASES += \
"DTypeDecl{1}=\Snippet{\1 =,;}" \
\DFuncDecl{<entityname>}
Inserts a Delphi code snippet with a function declaration.
-
ALIASES += \
"DFuncDecl{1}=\Snippet{\1(,):}" \
\DProcDecl{<entityname>}
Inserts a Delphi code snippet with a procedure declaration.
-
ALIASES += \
"DProcDecl{1}=\Snippet{\1(,);}" \
\DCompTypeDecl{<entityname>}
Inserts a Delphi code snippet with a compound (i.e. Record or Class) type declaration.
-
ALIASES += \
"DCompTypeDecl{1}=\Snippet{\1 =,; // \1}" \
\DCompVarDecl{<entityname>}
Inserts a Delphi code snippet with a compound (i.e. Record or Class) variable declaration.
-
ALIASES += \
"DCompVarDecl{1}=\Snippet{\1:,; // \1}" \
\DEnumTypeDecl{<entityname>}
Inserts a Delphi code snippet with an enumeration type declaration.
-
ALIASES += \
"DEnumTypeDecl{1}=\Snippet{\1 = (,);}" \
\DEnumVarDecl{<entityname>}
Inserts a Delphi code snippet with an enumeration variable declaration.
-
ALIASES += \
"DEnumVarDecl{1}=\Snippet{\1: (,);}" \
\DConstDecl{<entityname>}
equivalent to \DVarDecl
\DDefDecl{<entityname>}
equivalent to \DTypeDecl
Inserting Delphi declarations: Summary
For the resp. limiting (first/last) line patterns s. following table; " ... " means any single or multiple lines of Delphi code sufficient to the resp. entity!
ALIASES = # (first line pattern) |...|(last line pattern)
# -------------------------|---|-------------------
"DVarDecl{1}=\Snippet{\1:,;}" # <variablename>: ... ;
"DFuncDecl{1}=\Snippet{\1(,):}" # <functioname>( ... ):
"DProcDecl{1}=\Snippet{\1(,);}" # <procedureame>( ... );
"DTypeDecl{1}=\Snippet{\1 =,;}" # <typename> = ... ;
"DCompTypeDecl{1}=\Snippet{\1 =,; // \1}" # <record|class typename> = ... ; \\ <record|class typename>
"DCompVarDecl{1}=\Snippet{\1:,; // \1}" # <record|class varname>: ... ; \\ <record|class varname>
"DEnumTypeDecl{1}=\Snippet{\1 = (,);}" # <enum typename> = ... ;
"DEnumVarDecl{1}=\Snippet{\1: (,);}" # <enum varname> = ... );
"DConstDecl{1}=\DVarDecl{\1}" # equivalent to DVarDecl
"DDefDecl{1}=\DTypeDecl{\1}" # equivalent to DVTypeDecl
- Note
(first/last line pattern) define the coding conventions declaring the particular entity; this may be adjusted to your preferred conventions, i.e. if you like the "=" just after the type name instead of space between, change the DTypeDecl alias definition to
ALIASES = "DTypeDecl{1}=\Snippet{\1=,;}"
with an "=" just after the argument.
Special ALIASES to include C++Builder Code
These commands are intended to include C++Builder header code into the documentation; this may be useful to document the API of a DLL.
Main Commands
As like the Delphi Main commands these are sufficient to include code snippets from C++Builder .hpp files. For special purposes or more detailed or more sophisticated documentation s. next chapter.
Each command has hat least two arguments:
- name of the entity to document
- name of the C++Builder module including this entity, i.e. .hpp file without extension ".hpp"
- Note
- The explicit notation of the module name is the only general overhead
- Additional overhead is made for documenting class and struct members: as the documentation is (from Doxygen's point of view) outside the entity's scope, the class / struct name is required to inform Doxygen to which upper scope the documentation belongs.
- C++Builder .hpp files must be available via EXAMPLE_PATH.
\CClass{<classname>,<modulename>}
Including a C++Builder class declaration
- Arguments:
- class name
- name of the C++Builder module including this entity, i.e. .hpp file without extension ".hpp"
- Attention
- Proper including a C++Builder class declaration needs a work around!
-
ALIASES += \
"CClass{2}=\CDeclHdr{\2,\1} \CClassDecl{\1}" \
- Example:
157 //! Class derived from default class TClass2 \n
158 //! Whole class incl. members only C++Builder declaration documented
160 //! @CClass{TClass4,Example_CLASS}
162 TClass4 = class(TClass2)
163 //! ------------------------------------------------- [EXAMPLE_CLASS4_FIELD]
165 //! @Dmember{TClass4,Field4}
166 //! @brief TClass 4 / Field 4
167 //! @CClassVar{TClass4,Field4,Example_CLASS}
170 //! ------------------------------------------------- [EXAMPLE_CLASS4_FIELD]
172 //! -------------------------------------------------- [EXAMPLE_CLASS4_FUNC]
174 //! @Dmethod{TClass4,Func4}
175 //! @brief TClass 4 / Func 4
177 //! @CClassMethod{TClass4,Func4,Example_CLASS}
179 FUNCTION Func4(): INTEGER;
180 //! -------------------------------------------------- [EXAMPLE_CLASS4_FUNC]
182 //! -------------------------------------------------- [EXAMPLE_CLASS4_PROC]
184 //! @Dmethod{TClass4,Proc4}
185 //! @brief TClass 4 / Proc 4
187 //! @CClassMethod{TClass4,Proc4,Example_CLASS}
190 //! -------------------------------------------------- [EXAMPLE_CLASS4_PROC]
192 //! -------------------------------------------------- [EXAMPLE_CLASS4_PROP]
194 //! @Dproperty{TClass4,Prop4}
195 //! @brief property TClass 4 / Prop 4
197 //! @CClassProperty{TClass4,Prop4,Example_CLASS}
199 property Prop4: INTEGER read Field4 write Field4; // Prop4
200 //! -------------------------------------------------- [EXAMPLE_CLASS4_PROP]
203 destructor Dtor(void: TClass4 = NIL); virtual;
- Resulting documentation:
- TClass4
More Examples s. Example_CLASS.pas.
\CClassMethod{<classname>,<function_methodname>,<modulename>}
Including a C++Builder class method (function) declaration
- Arguments:
- class name
- class function name
- name of the C++Builder module including this entity, i.e. .hpp file without extension ".hpp"
-
ALIASES += \
"CClassMethod{3}=\CDeclHdr{\3,\1_\2} \CClassMethodDecl{\1,\2}" \
- Example:
174 //! @Dmethod{TClass4,Func4}
175 //! @brief TClass 4 / Func 4
177 //! @CClassMethod{TClass4,Func4,Example_CLASS}
179 FUNCTION Func4(): INTEGER;
- Resulting documentation:
- TClass4::Func4
More Examples s. Example_CLASS.pas.
\CClassVar{<classname>,<class_variablename>,<modulename>}
Including a C++Builder class variable declaration
- Arguments:
- class name
- class variable name
- name of the C++Builder module including this entity, i.e. .hpp file without extension ".hpp"
-
ALIASES += \
"CClassVar{3}=\CDeclHdr{\3,\1_\2} \CClassVarDecl{\1,\2}" \
- Example:
165 //! @Dmember{TClass4,Field4}
166 //! @brief TClass 4 / Field 4
167 //! @CClassVar{TClass4,Field4,Example_CLASS}
- Resulting documentation:
- TClass4::Field4
More Examples s. Example_CLASS.pas.
\CClassProperty{<classname>,<class_propertyname>,<modulename>}
Including a C++Builder class property declaration
- Arguments:
- class name
- class property name
- name of the C++Builder module including this entity, i.e. .hpp file without extension ".hpp"
-
ALIASES += \
"CClassProperty{3}=\CDeclHdr{\3,\1_\2} \CClassPropertyDecl{\1,\2}" \
- Example:
194 //! @Dproperty{TClass4,Prop4}
195 //! @brief property TClass 4 / Prop 4
197 //! @CClassProperty{TClass4,Prop4,Example_CLASS}
199 property Prop4: INTEGER read Field4 write Field4; // Prop4
- Resulting documentation:
- TClass4::Prop4
More Examples s. Example_CLASS.pas.
\CStruct{<struct_typename>,<modulename>}
Including a C++Builder record type declaration
- Arguments:
- record type name
- name of the C++Builder module including this entity, i.e. .hpp file without extension ".hpp"
-
ALIASES += \
"CStruct{2}=\CDeclHdr{\2,\1} \CStructDecl{\1}" \
\CEnum{<enum-typename>,<modulename>}
Including a C++Builder enumeration type declaration
- Arguments:
- enumeration type name
- name of the C++Builder module including this entity, i.e. .hpp file without extension ".hpp"
-
ALIASES += \
"CEnum{2}=\CDeclHdr{\2,\1} \CEnumDecl{\1}" \
\CFunc{<functionname>,<modulename>}
Including a C++Builder function declaration
- Arguments:
- function name
- name of the C++Builder module including this entity, i.e. .hpp file without extension ".hpp"
-
ALIASES += \
"CFunc{2}=\CDeclHdr{\2,\1} \CFuncDecl{\1}" \
- Example:
54 //! @DFunc{ReplaceFunc,Example_FUNC}
55 //! @brief replaces ASCII-ctrlchars
57 //! @CFunc{ReplaceFunc,Example_FUNC}
59 //! replaces ASCII-ctrlchars with blanks, nothing, name or hex depending
60 //! depending on whether the char is included in the respective ReplaceXxxx set
62 //! @param AString Input string
63 //! @param ReplaceBlanks set with ctrlchars to replace by Spaces
64 //! @param ReplaceNone set with ctrlchars to delete
65 //! @param ReplaceName set with ctrlchars to replace by their names
66 //! @param ReplaceHex set with ctrlchars to replace by their hex representation
67 //! @result AString with replaced ctrlchars
69 //! @note uses typed CONST @ref ASCIINames
71 FUNCTION ReplaceFunc(AString: AnsiString;
72 // TASCIICtrlSets zur Behandlung von Ctrl-Zeichen:
74 CONST ReplaceBlanks, // ...ersetzen durch Blanks
75 ReplaceNone, // ...entfernen
76 ReplaceName, // ...ersetzen durch den Namen
77 ReplaceHex: // ...ersetzen durch Hex
78 TASCIICtrlSet): AnsiString;
- Resulting documentation:
- ReplaceFunc
More Examples s. Example_FUNC.pas.
\CVar{[<typename>,]<variablename>,<modulename>}
Including a C++Builder var, initialized var or typed const declaration
- Arguments:
- type name
- variable name
- name of the C++Builder module including this entity, i.e. .hpp file without extension ".hpp"
<typename>
may be ommited if <variablename>
is unique (i.e. no other entities with same name in the whole module, neither as class / struct members!).
-
ALIASES += \
"CVar{3}=\CDeclHdr{\3,\1_\2} \CVarDecl{\1,\2}" \
\CType{<typename>,<modulename>}
Including a C++Builder type declaration.
- Arguments:
- type name
- name of the C++Builder module including this entity, i.e. .hpp file without extension ".hpp"
-
ALIASES += \
"CType{2}=\CDeclHdr{\2,\1} \CTypeDecl{\1}" \
- Example:
25 //! @DType{TASCIICtrls, Example_TYPE}
26 //! @brief enumeration of ASCII-ctrlchars
28 TYPE TASCIICtrls = #$00..#$1F;
More Examples s. Example_TYPE.pas.
\CDef{<macro-name>,<modulename>}
Including a C++Builder macro (#define) declaration.
- Arguments:
- macro name
- name of the C++Builder module including this entity, i.e. .hpp file without extension ".hpp"
Intended to document Delphi CONSTs converted to C/C++ macros: not used since Delphi converts these to C/C++ const's.
- Note
- Actually macros aren't created by Delphi, but may be used to include documentation for macros inserted by {$HPPEMIT ...}
-
ALIASES += \
"CDef{2}=\CDeclHdr{\2,\1} \CDefDecl{\1}"
Low level commands
The Main commands are sufficient for all purposes to include C/C++ code snippets. Like the Delphi related commands each C/C++ related alias consists of several Doxygen special commands. To simplify/unify the alias definition they are composed on a couple of lower level aliases which can be used to do more sophisticated documentation and/or to create your own aliases.
Each of the above aliases consists of 2 parts:
- \CDeclHdr{..}
displays the headline and loads the C++Builder module
- \C<Entity>Decl{..}
Finally inserts the C++Builder code snippet for the desired entity
Common usable aliases; may also used for other purposes as documenting Delphi code:
And special aliases to include C/C++ code extracted from the C++Builder .hpp files:
— Helper commands —
Common usable aliases; may also used for other purposes as documenting Delphi code:
\InclHpp{<modulename>}
Helper command:
- Arguments:
- module name: C++Builder .hpp file name (without extension ".hpp")
Sets the C++Builder header filename with ".hpp".
-
ALIASES += \
"InclHpp{1}=\dontinclude \1.hpp ^^ " \
\CHeader{[<anchorname>]}
Helper command:
- optional Arguments:
- anchor name
Starts a section with headline "C++Builder Declaration"; optionally places an anchor <anchor>_hpp
before the section.
-
ALIASES += \
"CHeader=\par C++Builder Declaration ^^ " \
"CHeader{1}=\anchor \1_hpp ^^ \CHeader " \
\CDeclHdr{<modulename>,<anchorname>}
Helper command:
- Arguments:
- module name: C++Builder .hpp file name (without extension ".hpp")
- anchor name
Starts declaration section with headline "C++Builder Declaration" with an anchor before and sets the C++Builder .hpp file name.
-
ALIASES += \
"CDeclHdr{2}=\CHeader{\2} \InclHpp{\1}" \
— Commands to include snippets with C/C++ entity declarations —
Each of the following C<Entity>Decl aliases' inserts a C++Builder code snippet from a previously set include file for a special entity <entityname>. The limiting line patterns are implicitly defined by the kind how the <Entity>'s declaration in the .hpp file are generated by Delphi. In the end these coding convention are mapped by the aliases.
- Note
- All declarations are written in one line in the the .hpp file, with the exception of class and struct declarations!
\CClassDecl{<classname>}
Inserts a C++Builder code snippet with a class declaration.
- Attention
- This is the only one which needs a work around in the Delphi code!
C++Builder class declaration is created as follows:
class PASCALIMPLEMENTATION <classname> : <ancestor(s)>
{
...class members...
};
So the limiting Snippet lines may contain "\<classname\> :"
and "};"
. But since the class members' declaration may also contain };
this limiter is not unique!
As there is no possibility to insert specifically any text, a work around is needed:
In fact Delphi creates the class member declaration in the given order, i.e. the last declaration in the Delphi source is also the last declaration in the C++Builder .hpp file. After this last declaration Delphi inserts eventually needed constructors or destructors provided by the ancestor class(es).
Also the Delphi declaration must include a last member that
- must be unique
- doesn't interfere with ancestor declarations
Thus as last declaration a dummy destructor may be included in the Delphi code:
TYPE <classname> = class(<ancestor(s)>
...class members...
private // to avoid accidentally use!
destructor Dtor(void: <classname>); virtual; // Dummy destructor
end;
This results in C++Builder code:
class PASCALIMPLEMENTATION <classname> : <ancestor(s)>
{
...class members...
private:
__fastcall virtual ~<classname>(<classname>* Void);
public:
...additional ancestor declaration as needed...
};
Thus including a class declaration snippet is done in two steps (which are seamless concatenated by Doxygen):
- skip to the beginning of the class declaration and include the code snippet
- from the line containing
<classname> :
- up to the line containing
~<classname>(<classname>
- then append the next lines up to the line containing the closing
};
- The resulting ALIAS:
-
ALIASES += \
"CClassDecl{1}=\Snippet{\1 :,~\1(\1} \until };" \
\CClassMethodDecl{<methodname>}
Inserts a C++Builder code snippet with a class method declaration.
- skip to the beginning of the class declaration
- skip to the method name and display this line
-
ALIASES += \
"CClassMethodDecl{2}=\SkipSnippet{\1 :,\2(}" \
- Note
- The opening
(
is directly behind the function's / method's names without any space between.
\CClassVarDecl{<varname>}
Inserts a C++Builder code snippet with a class variable declaration.
- skip to the beginning of the class declaration
- skip to the variable name and display this line
-
ALIASES += \
"CClassVarDecl{2}=\SkipSnippet{\1 :,\2;}" \
- Note
- The closing
;
is directly behind the variable's name without any space between.
CClassPropertyDecl
Inserts a C++Builder code snippet with a class property declaration.
- skip to the beginning of the class declaration
- skip to the property name and display this line
-
ALIASES += \
"CClassPropertyDecl{2}=\SkipSnippet{\1,\2 = \\{}" \
- Note
- The property name is followed by
= {
with exactly one space around the "="
.
\CStructDecl{<structname>}
Inserts a C++Builder code snippet with a struct declaration.
- include a code snippet beginning with
enum DECLSPEC_DRECORD <structname>
and ending with };
-
ALIASES += \
"CStructDecl{1}=\Snippet{struct DECLSPEC_DRECORD \1,\};}" \
- Note
- The closing
;
is directly behind the }
without any space between.
\CEnumDecl{<enumname>}
Inserts a C++Builder code snippet with an enum declaration.
- include a code snippet beginning with
enum DECLSPEC_DENUM <strauctname> :
and ending with };
-
ALIASES += \
"CEnumDecl{1}=\Snippet{enum DECLSPEC_DENUM \1 :,\};}" \
- Note
- The closing
;
is directly behind the }
without any space between.
\CFuncDecl{<functionname>}
Inserts a C++Builder code snippet with a function declaration.
- include a code line containing
<functionname>(
-
ALIASES += \
"CFuncDecl{1}=\skipline \1(" \
- Note
- The opening
(
is directly behind the <functionname>
without any space between.
\CVarDecl{[<typename>,]<variablename>}
Inserts a C++Builder code snippet with a variable declaration.
- include a code line containing
DELPHI_PACKAGE <typename> <variablename>;
<typename>
may be ommited if <variablename>
is unique (i.e. no other entities with same name in the whole module, neither as class / struct members!).
-
ALIASES += \
"CVarDecl{2}=\skipline DELPHI_PACKAGE \1 \2;" \
- Note
- DELPHI_PACKAGE, <typename> and <variablename> are seperated by exacly one space.
- The closing
;
is directly behind the <variablename>
without any space between.
\CTypeDecl{<typename>}
Inserts a C++Builder code snippet with a type declaration.
- include a code line containing
<typename>;
-
ALIASES += \
"CTypeDecl{1}=\skipline \1;" \
- Note
- The closing
;
is directly behind the <typename>
without any space between.
\CDefDecl{<macroname>}
Inserts a C++Builder code snippet with a macro declaration.
- include a code line containing
#define <macroname>
-
ALIASES += \
"CDefDecl{1}=\skipline #define \1" \
- Note
- Delphi doesn't generate macros, but they may be inserted manually via
{$HPPEMIT ...}
directives; so be aware the following conventions are met:
- Between
#define
and <macroname>
is exactly one space.
- The macro declaration must be in one single line!