Whither Fortran type-bound procedure documentation?

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Whither Fortran type-bound procedure documentation?

Hambley, Matthew
My original attempt to send this overtook my joining the mailing list so it is lost in limbo somewhere.

Doxygen's approach to type-bound procedures in Fortran seems a little problematic. I've looked through my Doxyfile but can't see anything obvious which I should be changing but haven't.

Let me elucidate:

There are two places where one could put the documentation. Along with the declaration of the procedure, in the type definition. Alternatively it could go with the definition in the module body.

Currently Doxygen seems to expect it to accompany declaration and ignores anything provided with definition.

There are a number of issues with this.

The calling signature of the procedure is not described in the declaration so Doxygen complains that you have @param clauses for non-existent arguments. Of course they do exist, just down in the definition.

If you have a "generic" procedure, one which maps to a number of different implementations, i.e. overloaded, It can not be sensibly documented at declaration as there are multiple procedures but only one comment block.

The upshot of all this is that the support for documentation seems to be in the wrong place. It would seem to make more sense for it to be with the procedure definition in the module body rather than in the module header in the type definition.

Am I missing something? Is there already a way to get the behaviour I want? Or is this a shortcoming in the tool?

--
Matthew Hambley
  Scientific Software Engineer
  Met Office Hadley Centre, Exeter, UK



------------------------------------------------------------------------------
_______________________________________________
Doxygen-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/doxygen-users
Reply | Threaded
Open this post in threaded view
|

Re: Whither Fortran type-bound procedure documentation?

albert
Matthew,

Can you create a small  example to show the short comings?

Best Regards,

Albert

On Thu, Sep 22, 2016 at 11:25 AM, Hambley, Matthew <[hidden email]> wrote:
My original attempt to send this overtook my joining the mailing list so it is lost in limbo somewhere.

Doxygen's approach to type-bound procedures in Fortran seems a little problematic. I've looked through my Doxyfile but can't see anything obvious which I should be changing but haven't.

Let me elucidate:

There are two places where one could put the documentation. Along with the declaration of the procedure, in the type definition. Alternatively it could go with the definition in the module body.

Currently Doxygen seems to expect it to accompany declaration and ignores anything provided with definition.

There are a number of issues with this.

The calling signature of the procedure is not described in the declaration so Doxygen complains that you have @param clauses for non-existent arguments. Of course they do exist, just down in the definition.

If you have a "generic" procedure, one which maps to a number of different implementations, i.e. overloaded, It can not be sensibly documented at declaration as there are multiple procedures but only one comment block.

The upshot of all this is that the support for documentation seems to be in the wrong place. It would seem to make more sense for it to be with the procedure definition in the module body rather than in the module header in the type definition.

Am I missing something? Is there already a way to get the behaviour I want? Or is this a shortcoming in the tool?

--
Matthew Hambley
  Scientific Software Engineer
  Met Office Hadley Centre, Exeter, UK



------------------------------------------------------------------------------
_______________________________________________
Doxygen-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/doxygen-users


------------------------------------------------------------------------------

_______________________________________________
Doxygen-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/doxygen-users
Reply | Threaded
Open this post in threaded view
|

Re: Whither Fortran type-bound procedure documentation?

Hambley, Matthew
From: Albert [mailto:[hidden email]]
>
> Can you create a small  example to show the short comings?

Of course. What follows is a Fortran module which should illustrate what I am trying to describe. (Object Fortran is, sadly, never short)

Having carefully laid it out I suddenly had a nasty realisation that Outlook is probably about to mangle it horrible so I've attached a copy as well. Skip past the source code for commentary.

module test_mod

  use iso_fortran_env, only : output_unit

  implicit none

  private

  !> @brief Type which does a thing
  !> @details Documented where we would expect.
  !>
  type, public :: test_type

    private

    integer, allocatable :: foo(:)

  contains

    private
    !> @brief Document in the type declaration
    !> @details Not so good as there are no arguments here. If they are
    !>          documented here they show up in documentation but Doxygen
    !>          complains about them being documented but not existing. Of
    !>          course they do, but further down.
    !>
    !>          Regardless the documentation is separate from the
    !>          implementation.
    !> @param teapot Some argument.
    !>
    procedure, public :: wobble
    procedure, public :: wubble
    generic,   public :: wibble => wibble_integer, wibble_real

    !> @brief One aspect of wibble
    !> @details I can document this here but it appears as a method of
    !>          the type whereas really it should appear under
    !>          "wibble". After all, it is private and not part of the
    !>          API.
    !>
    procedure wibble_integer
    procedure wibble_real

    final :: destroy_test

  end type test_type

  interface test_type
    procedure create_test_default
    !> @brief Specific initialiser
    !> @details Will this how up? No it will not.
    procedure create_test_specific
  end interface test_type

contains

  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  !> @brief Default initialiser
  !>
  !> @details It would be nice to document this here but it wont show up.
  !>
  function create_test_default() result(new_test)

    implicit none

    type(test_type) :: new_test

    allocate( new_test%foo(10) )
  end function create_test_default

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
function create_test_specific( tally ) result(new_test)

    implicit none

    integer, intent(in) :: tally

    type(test_type) :: new_test

    allocate( new_test%foo(tally) )

  end function create_test_specific

  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  !> @brief Destructor.
  !> @details Would prefer to document this here.
  !>
  subroutine destroy_test( this )

    implicit none
    type(test_type), intent(inout) :: this

    deallocate( this%foo )

  end subroutine destroy_test

  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  !> @brief A more sensible place to document.
  !> @details But it does not appear.
  !> @param teapot Some other argument.
  !>
  subroutine wobble( this, teapot )

    implicit none

    class(test_type), intent(in) :: this
    integer,          intent(in) :: teapot

    write( output_unit, '("wobble ", I0)' ) teapot

  end subroutine wobble

  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  subroutine wubble( this, cheese )

    implicit none

    class(test_type), intent(in) :: this
    integer,          intent(in) :: cheese

    write( output_unit, '("wubble ", I0)' ) cheese

  end subroutine wubble

  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  subroutine wibble_integer( this, value )

    implicit none

    class(test_type), intent(inout) :: this
    integer,         intent(in) :: value

    write( output_unit, '("wibble ", I0)' ) value

  end subroutine wibble_integer

  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  !> @brief Again I would like to document this here.
  !> @details But again it will not show up.
  !> @param value A floating point argument.
  !>
  subroutine wibble_real( this, value )

    implicit none

    class(test_type), intent(inout) :: this
    real,            intent(in) :: value

    write( output_unit, '("wibble ", F14.4)' ) value

  end subroutine wibble_real

end module test_mod

Running this through Doxygen I get the following messages:

test_mod.f90:29: warning: Member wubble (function) of class test_mod::test_type is not documented.

Of course it is, but at the definition rather than the declaration.

test_mod.f90:30: warning: Member wibble=> wibble_integer, wibble_real (function) of class test_mod::test_type is not documented.

This is sort of true except wibble is documented by wibble_integer and wibble_real.

test_mod.f90:38: warning: Member wibble_real (function) of class test_mod::test_type is not documented.

It is, but further down.

test_mod.f90:40: warning: Member destroy_test (function) of class test_mod::test_type is not documented.

Again, it is, but further down.

test_mod.f90:13: warning: Member foo (variable) of class test_mod::test_type is not documented.

True but irrelevant to the current issue.

test_mod.f90:22: warning: argument 'teapot' of command @param is not found in the argument list of test_mod::test_type::wobble()

It does, but at definition, not declaration.

I realise that this is all pretty esoteric stuff and that there isn't a lot of object Fortran around but if you can suggest a solution I would be very grateful.

------------------------------------------------------------------------------

_______________________________________________
Doxygen-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/doxygen-users

test_mod.f90 (4K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Whither Fortran type-bound procedure documentation?

albert
Matthew,

Thank you for the example.
I see indeed a feature tthat is not supported yet in doxygen:
generic,   public :: wibble => wibble_integer, wibble_real

It will take a it of time before I can have a good look at this problem.


Albert


On Thu, Sep 22, 2016 at 3:45 PM, Hambley, Matthew <[hidden email]> wrote:
From: Albert [mailto:[hidden email]]
>
> Can you create a small  example to show the short comings?

Of course. What follows is a Fortran module which should illustrate what I am trying to describe. (Object Fortran is, sadly, never short)

Having carefully laid it out I suddenly had a nasty realisation that Outlook is probably about to mangle it horrible so I've attached a copy as well. Skip past the source code for commentary.

module test_mod

  use iso_fortran_env, only : output_unit

  implicit none

  private

  !> @brief Type which does a thing
  !> @details Documented where we would expect.
  !>
  type, public :: test_type

    private

    integer, allocatable :: foo(:)

  contains

    private
    !> @brief Document in the type declaration
    !> @details Not so good as there are no arguments here. If they are
    !>          documented here they show up in documentation but Doxygen
    !>          complains about them being documented but not existing. Of
    !>          course they do, but further down.
    !>
    !>          Regardless the documentation is separate from the
    !>          implementation.
    !> @param teapot Some argument.
    !>
    procedure, public :: wobble
    procedure, public :: wubble
    generic,   public :: wibble => wibble_integer, wibble_real

    !> @brief One aspect of wibble
    !> @details I can document this here but it appears as a method of
    !>          the type whereas really it should appear under
    !>          "wibble". After all, it is private and not part of the
    !>          API.
    !>
    procedure wibble_integer
    procedure wibble_real

    final :: destroy_test

  end type test_type

  interface test_type
    procedure create_test_default
    !> @brief Specific initialiser
    !> @details Will this how up? No it will not.
    procedure create_test_specific
  end interface test_type

contains

  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  !> @brief Default initialiser
  !>
  !> @details It would be nice to document this here but it wont show up.
  !>
  function create_test_default() result(new_test)

    implicit none

    type(test_type) :: new_test

    allocate( new_test%foo(10) )
  end function create_test_default

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
function create_test_specific( tally ) result(new_test)

    implicit none

    integer, intent(in) :: tally

    type(test_type) :: new_test

    allocate( new_test%foo(tally) )

  end function create_test_specific

  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  !> @brief Destructor.
  !> @details Would prefer to document this here.
  !>
  subroutine destroy_test( this )

    implicit none
    type(test_type), intent(inout) :: this

    deallocate( this%foo )

  end subroutine destroy_test

  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  !> @brief A more sensible place to document.
  !> @details But it does not appear.
  !> @param teapot Some other argument.
  !>
  subroutine wobble( this, teapot )

    implicit none

    class(test_type), intent(in) :: this
    integer,          intent(in) :: teapot

    write( output_unit, '("wobble ", I0)' ) teapot

  end subroutine wobble

  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  subroutine wubble( this, cheese )

    implicit none

    class(test_type), intent(in) :: this
    integer,          intent(in) :: cheese

    write( output_unit, '("wubble ", I0)' ) cheese

  end subroutine wubble

  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  subroutine wibble_integer( this, value )

    implicit none

    class(test_type), intent(inout) :: this
    integer,         intent(in) :: value

    write( output_unit, '("wibble ", I0)' ) value

  end subroutine wibble_integer

  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  !> @brief Again I would like to document this here.
  !> @details But again it will not show up.
  !> @param value A floating point argument.
  !>
  subroutine wibble_real( this, value )

    implicit none

    class(test_type), intent(inout) :: this
    real,            intent(in) :: value

    write( output_unit, '("wibble ", F14.4)' ) value

  end subroutine wibble_real

end module test_mod

Running this through Doxygen I get the following messages:

test_mod.f90:29: warning: Member wubble (function) of class test_mod::test_type is not documented.

Of course it is, but at the definition rather than the declaration.

test_mod.f90:30: warning: Member wibble=> wibble_integer, wibble_real (function) of class test_mod::test_type is not documented.

This is sort of true except wibble is documented by wibble_integer and wibble_real.

test_mod.f90:38: warning: Member wibble_real (function) of class test_mod::test_type is not documented.

It is, but further down.

test_mod.f90:40: warning: Member destroy_test (function) of class test_mod::test_type is not documented.

Again, it is, but further down.

test_mod.f90:13: warning: Member foo (variable) of class test_mod::test_type is not documented.

True but irrelevant to the current issue.

test_mod.f90:22: warning: argument 'teapot' of command @param is not found in the argument list of test_mod::test_type::wobble()

It does, but at definition, not declaration.

I realise that this is all pretty esoteric stuff and that there isn't a lot of object Fortran around but if you can suggest a solution I would be very grateful.


------------------------------------------------------------------------------

_______________________________________________
Doxygen-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/doxygen-users
Reply | Threaded
Open this post in threaded view
|

Re: Whither Fortran type-bound procedure documentation?

Hambley, Matthew
From: Albert [mailto:[hidden email]]
>
> Thank you for the example.
>
> I see indeed a feature tthat is not supported yet in doxygen:
> generic,   public :: wibble => wibble_integer, wibble_real
>
> It will take a it of time before I can have a good look at this
> problem.

While we would like a solution to these issues at some point, most of our code is written in Fortran 90 style so these problems don't arise. So we are happy to wait until it is convenient for you.

You don't explicitly address it so can you confirm that you understand the issue regarding the placement of argument documentation.

That type-bound procedures can be documented in the type declaration but not their arguments as they do not appear there. Meanwhile they can't be documented at the procedure definitions where the arguments do appear.

--
Matthew Hambley
  Scientific Software Engineer
  Met Office Hadley Centre, Exeter, UK



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
Doxygen-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/doxygen-users