Skip to content

Commit

Permalink
Merge pull request #645 from Fortran-FOSS-Programmers/submodule-links
Browse files Browse the repository at this point in the history
Enable linking to submodules
  • Loading branch information
ZedThree committed Apr 3, 2024
2 parents bbba0b4 + aa3e624 commit 8e05e45
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 28 deletions.
7 changes: 7 additions & 0 deletions docs/api/ford._markdown.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
ford._markdown module
==========================

.. automodule:: ford._markdown
:members:
:undoc-members:
:show-inheritance:
1 change: 1 addition & 0 deletions docs/api/ford.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Submodules
ford.fortran_project
ford.graphs
ford.intrinsics
ford._markdown
ford.md_admonition
ford.md_environ
ford.md_striped_table
Expand Down
13 changes: 7 additions & 6 deletions docs/developers_guide/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,19 @@ This is a very rough outline of how FORD works internally.
#. After each file has been parsed, the lists of entities are added to
the `Project`'s lists of all the entities in the whole project.

#. After all the files have been parsed, the documentation comments are
converted from Markdown to HTML, recursively down from the source
files. At this point, metadata in the comments is also parsed.

#. Entities defined in other files are now "correlated" with their
concrete objects. This is done recursively from
`Project.correlate`, first by finding which modules are ``use``\ d
by each entity, and then looking up names in the corresponding
`FortranModule`.

#. Another recursive pass is done of the project to convert internal
`links <writing-links>` to actual HTML links using `sub_links`.
#. After all the files have been parsed, the documentation comments
are converted from Markdown to HTML, recursively down from the
source files. At this point, metadata in the comments is also
parsed. Several markdown extensions, `AliasPreprocessor`,
`FordLinkProcessor`, `RelativeLinksTreeProcessor`, handle aliases,
links, and absolute to relative link conversion respectively. The
`MetaMarkdown` class just wraps constructing the markdown object.

#. The static pages are processed with `get_page_tree`.

Expand Down
74 changes: 56 additions & 18 deletions docs/user_guide/writing_documentation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ the source-code this way. This::
!! The ammount of pet food (in kilograms) which you have on hand.
integer, intent(out) :: angry
!! The number of pets angry because they weren't fed.

!...
return
end subroutine feed_pets
Expand All @@ -65,7 +65,7 @@ looks better/more readable than::
real, intent(inout) :: food
!! The number of pets angry because they weren't fed.
integer, intent(out) :: angry

!...
return
end subroutine feed_pets
Expand Down Expand Up @@ -280,35 +280,73 @@ this is ``[[component(type):item(type)]]``:
as a type and its public constructor). If multiple items with the
same name exist and ``type`` is not specified then FORD’s behaviour
is undefined; it will link to the first of those items which it
finds. The available options are “procedure”, “subroutine”,
“function”, “proc” (all of which are interchangeable and specify a
procedure), “interface”, “absinterface” (both of which are for
abstract interfaces), “block” (for the legacy ``block data`` program
unit), and “type”, “file”, “module”, and “program” (which are
self-explanatory).
finds. The available options are:

- "procedure", "proc", "subroutine", "function" for any kind of
procedure defined within the project
- "interface", "absinterface" for abstract interfaces
- "block" for the legacy ``block data`` construct
- "type"
- "file"
- "module"
- "submodule"
- "program"
- "namelist"

The majority of these can also be prefixed with "ext" to refer to
entities defined in `external projects <option-external>`
- ``item`` (optional) specifies an item within ``component`` which is
to be linked to. The link’s target will be ``item``\ ’s location on
``component``\ ’s page. If ``item`` is not present then the colon in
the link must be omitted.
- ``type`` (optional, but ``item`` must also be present) is
``item``\ ’s type of Fortran construct. It can be used in the same
manner as the component ``type``, but has different options. These
are “variable”, “type”, “constructor”, “interface”, “absinterface”
(abstract interface), “subroutine”, “function”, “final” (finalization
procedure), “bound” (type-bound procedure), “modproc” (module
procedure in a generic interface block), and “common”. None of these
options are interchangeable. If no description is given then its
meaning should be self-explanatory. If you specify an option that can
not exist within ``component`` (for example, if ``component`` is a
module and ``item`` is “bound”) then a warning message is issued and
the link is not generated.
manner as the component ``type``, but has different options:

- "absinterface" for abstract interfaces
- "bound" for type-bound procedures
- "common" for ``common`` blocks
- "constructor" for structure constructor procedures
- "final" for finalization procedures
- "function"
- "interface"
- "modproc" for module procedures in generic interfaces
- "subroutine"
- "type"
- "variable"

None of these options are interchangeable. If you specify an option
that can not exist within ``component`` (for example, if
``component`` is a module and ``item`` is “bound”) then a warning
message is issued and the link is not generated.

For example, to link to a module called ``my_mod`` you could
use ``[[my_mod]]`` or ``[[my_mod(module)]]``, while if you wanted to
refer to a function called ``my_function`` in that module you could
use any of (from least to most specific):

- ``[[my_function]]``
- ``[[my_function(function)]]``
- ``[[my_function(proc)]]``
- ``[[my_mod:my_function]]``
- ``[[my_mod(module):my_function]]``
- ``[[my_mod:my_function(function)]]``
- ``[[my_mod(module):my_function(function)]]``

If you have an overridden constructor a derived type, then it is
strongly recommended that you specify ``item`` should you wish to link
to either of them. Otherwise FORD will not know whether you are
referring to the derived type itself or the interface for its
constructor.

.. versionchanged:: 7.0.0
Previously, links inside code blocks (with backticks) were
resolved, now they are left verbatim, as with all other
markup. That is, pre-v7, ```call [[my_subroutine]]``` would be
rendered as ``call my_subroutine`` with a link to
``my_subroutine``, while now it will be left as: ``call
[[my_subroutine]]``.

.. _non-fortran-source-files:

Non-Fortran Source Files
Expand Down
1 change: 0 additions & 1 deletion ford/_markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ def __init__(
aliases: Optional[Dict[str, str]] = None,
project: Optional[Project] = None,
):
"""make thing"""

default_extensions: List[Union[str, Extension]] = [
"markdown_include.include",
Expand Down
1 change: 1 addition & 0 deletions ford/fortran_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@

LINK_TYPES = {
"module": "modules",
"submodule": "submodules",
"extmodule": "extModules",
"type": "types",
"exttype": "extTypes",
Expand Down
14 changes: 11 additions & 3 deletions test/test_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -1043,7 +1043,7 @@ def test_submodule_uses(copy_fortran_file):


def test_make_links(copy_fortran_file):
links = "[[a]] [[b(type)]] [[b:c]] [[a:d]] [[b:e]] [[F(proc)]] [[A:G]] [[H]]"
links = "[[a]] [[b(type)]] [[b:c]] [[a:d]] [[b:e]] [[F(proc)]] [[A:G]] [[H]] [[I]]"

data = f"""\
module a !! {links}
Expand Down Expand Up @@ -1073,6 +1073,9 @@ def test_make_links(copy_fortran_file):
program h !! {links}
end program h
submodule (a) i !! {links}
end submodule i
"""
settings = copy_fortran_file(data)
project = create_project(settings)
Expand All @@ -1088,6 +1091,7 @@ def test_make_links(copy_fortran_file):
"f": "../proc/f.html",
"g": "../module/a.html#variable-g",
"h": "../program/h.html",
"i": "../module/i.html",
}

for item in chain(
Expand All @@ -1106,7 +1110,7 @@ def test_make_links_with_entity_spec(copy_fortran_file):
links = (
"[[a(module)]] [[b(type)]] [[b(type):c(variable)]] "
"[[A(MODULE):D(SUBROUTINE)]] [[B(TYPE):E]] [[F(PROC)]] "
"[[A(module):G(variable)]] [[H(program)]]"
"[[A(module):G(variable)]] [[H(program)]] [[I(SUBMODULE)]]"
)

data = f"""\
Expand Down Expand Up @@ -1137,6 +1141,9 @@ def test_make_links_with_entity_spec(copy_fortran_file):
program h !! {links}
end program h
submodule (a) i !! {links}
end submodule i
"""
settings = copy_fortran_file(data)
project = create_project(settings)
Expand All @@ -1152,6 +1159,7 @@ def test_make_links_with_entity_spec(copy_fortran_file):
"f": "../proc/f.html",
"g": "../module/a.html#variable-g",
"h": "../program/h.html",
"i": "../module/i.html",
}

for item in chain(
Expand All @@ -1166,7 +1174,7 @@ def test_make_links_with_entity_spec(copy_fortran_file):
assert link_locations == expected_links, (item, item.name)


def test_link_with_context(copy_fortran_file):
def test_make_links_with_context(copy_fortran_file):
data = """\
module a !! [[g]]
type b !! [[c]] [[e]] [[g]]
Expand Down

0 comments on commit 8e05e45

Please sign in to comment.