-
Notifications
You must be signed in to change notification settings - Fork 4
XML Documentation Standard
Fortpy's XML Documentation standard allows code elements like subroutines, functions and user-defined types to be decorated with documentation describing what the code does, how to use it and what the parameters mean. The isense package that ships with Fortpy uses these documentation strings to provide real-time coding support. The unit testing package uses the docstrings to determine how to automate the unit testing of specific subroutines or functions.
Adding XML documentation to the code has an immediate payoff while you code. As soon as you have documented a code element, you get real-time support any time you reference it. One of the barriers to good scientific programming is that we often believe that the first draft of a program will never be seen or used by anyone else. We assume that we will document it later if it ever becomes useful to others. However, two months later we might not even remember the specifics of the various code elements, their call signatures and the exact format that certain parameters are supposed to be in. Adding the XML tags when the code is written ensures that all the necessary details are permanently available to you and anyone else who uses the code in the future. Once you start benefitting from the real-time code support, you will likely become addicted and it won't be such a drag to document your code properly.
You can place the XML documentation for each code element in one of two places:
- in a block of documentation that ends in the line immediately preceding the code element's signature. This is called "decorating" documentation.
- in the body of the code element between the signature and the end token (the end token has the form
end subroutine
orend function
).
**IMPORTANT: ** XML documentation is processed in BLOCKS. A block is a set of continuous documentation lines which all start with \s*!!
. By "continuous", we mean that there are no sets of double line breaks (i.e. "\n\n") anywhere in the code block. Whenever a "\n\n" is encountered, it is interpreted as terminating a documentation block.
For decorating documentation, the last line of the documentation block must be immediately before the signature of the code element that it decorates. If there is a blank line in between, the documentation will be interpreted as belonging to the body of the parent code element.
For body documentation blocks, the documentation can appear anywhere inside the body of the code element and the tags can appear in any order. That said, it is usually useful to keep the documentation close to the members they describe. NOTE: when methods or types are embedded in a subroutine, their documentation blocks are decorators. Although they appear in the body of the parent subroutine, they must appear immediately before the signature of the method or type in order to be applied correctly.
Some subroutines or functions sometimes have parameter lists with more than 10 arguments. Adding the documentation for all of these directly in the code file can make for a really long file! Fortpy supports the inclusion of external XML files for specifying additional documentation for code elements.
- Create an XML file with the same name as the Fortran code file, but use the extension
.xml
instead of.f90
. - Use
<fortpy mode="docstring">
as the root node in the XML file. - For each code element that you want to write documentation for, include a
<decorates name="module.code_element">
tag inside of the root<fortpy>
tag. In the name attribute, 'module' refers to the name of the module in the f90 that is parent to the code element and 'code_element' is the name of the subroutine, type or executable. For example, if I have a module called 'linalg' and a subroutine called 'invert', then the name attribute would be "linalg.invert" for the<decorates>
tag.
Fortpy can deal with mixed specifications. You can have some documentation in the .f90
file and other documentation in the .xml
file. You can even split the documentation for the same code element between the two files. This is especially useful for the unit testing package since you could put the parameter documentation in the .f90
file and then the unit testing directives in the external XML file.
The following lists the special tags that can be used to decorate the code elements.
These decorators can also be applied to embedded types, subroutines and functions inside of a subroutine.
-
<summary>
: summarizes why the code element exists and what it can accomplish. -
<usage>
: gives an example of how to use the code element to perform some task. -
<comments>
: gives additional information related to quirks in using the element or other special considerations that are easy to forget after a few months. -
<errors>
: summarize common problems encountered with the code element and their resolutions. Although it may seem really obvious what errors could be raised if you are familiar with the code, remember that someone who doesn't know the code will might still use the method and would appreciate such a summary. This is especially true when a high-level method has a stack that runs 6 or 7 methods deep and one of those deeper methods commonly causes problems when the high-level one gets called. If multiple errors are possible, you can nest each one in an<error>
child tag. -
<revision>
: when a major edit is made to a method or type you can include a revision tag to describe the change and why it was made. Attributes:- date: the date on which the revision was made.
- author: the name or initials of the developer who made the change.
These XML tags are found only in the body of the code element.
-
<member>
: describes a variable that belongs to the module or user-defined type. Attributes:- name: the symbol of the variable that the member documentation applies to.
These XML tags can either decorate the code element (i.e. be entered on a block of XML documentation immediately preceding the code element's signature), or be situated within the body of the code element (i.e. between the signature and the end token).
-
<parameter>
: describes one of the parameters in the call signature of the method. Parameter documentation can appear in any order above the method (i.e. doesn't need to be in the same order as the call signature). Attributes:- name: the symbol of the argument in the parameter list that this documentation applies to.
-
<local>
: describes a variable local to the method that cannot be accessed from any other code elements outside of the subroutine or function. Attributes:- name: the symbol of the variable that the member documentation applies to.
Is a child tag of either <parameter>
, <member>
or <local>
. IMPORTANT: when a dimension tag is nested inside of one of these tags, the summary can no longer appear as arbitrary text between the start and end tags. Instead, the summary should appear as an additional child tag <summary>
.
-
<dimension>
: describes the type and contents of array indices in specific dimensions. For example, we might document that the rows in an array represent each independent measurement taken in a certain experiment. Attributes:- type: either "row" or "column". Row only makes sense in 2D arrays. For 3+ dimensional arrays, use "column" and then specify the 'index' attribute.
- index: the one-based column index of the multi-dimensional array.
These should be found within a <group>
tag that has purpose="testing"
in order to have any value. See the unit testing documentation for a full explanation of these tags. For these tags, "target" refers to the method being tested by the unit testing framework. Since these tags have many attributes that are described in the unit testing documentation, we merely list them here for completeness.
-
<prereq>
: describes a method to run before the target can be tested. -
<instance>
: describes a variable that needs to have its value changed by direct assignment or by calling another function to return a value. -
<outcome>
: describes sets of tests to run to verify that the target generates the correct results. -
<mapping>
: tells the framework which variables to use during auto-matching of parameter names. -
<run>
: describes constraints on the expected run time. -
<global>
: describes a variable that needs to be initialized for use by one or more of the methods that will be called.
The <group>
tag performs a special function as a logical separator/grouper of documentation strings. When the documentation is parsed, Fortpy merely copies all the children of the group to code element it decorates as if they had been at a higher level. The group tag also has a purpose attribute (for example purpose="testing"
) that alters the behavior of Fortpy relative to the group's contents. In that case, the children are not just copied up a level. The primary purpose of groups is to allow the developer to group related documentation tags logically so that code is easier to maintain.
Groups can be nested to an arbitrary depth.
-
<group>
: surrounds sets of any other special documentation tags to declare them as a logical group. Attributes:- name: the identifier of the group. Serves no special purpose in the code except that it needs be unique within the element that it decorates or belongs to. Intended to be user-friendly and descriptive.
-
purpose: currently, the only special purpose implemented in Fortpy is
purpose="testing"
which identifies the group as holding unit testing data.
One of the primary motivations for using XML for the documentation is that developers can create their own tags and attributes for documenting their code. Although not yet available, the config.xml
file will soon have an <isense>
section that allows the real-time code support to be tailored specifically to the developers needs. By specifying tags and attributes to include in the tooltip, they can include custom tags that they created in the real-time documentation.