fortran-lang / fprettify

auto-formatter for modern fortran source code
https://pypi.python.org/pypi/fprettify
Other
368 stars 73 forks source link

Precompiler directives break indentation #138

Closed flokno closed 1 year ago

flokno commented 1 year ago

Hi,

precompiler directives such as #ifdef can break indentation, see for example this piece of code after reformatting with fprettify:

    module pure function lo_frobnorm(m) result(nrm)
        real(flyt), dimension(:, :), intent(in) :: m
        real(flyt) :: nrm
    end function
#ifdef AGRESSIVE_SANITY
    module function lo_trace(m) result(tr)
#else
        module pure function lo_trace(m) result(tr)
#endif
            real(flyt), dimension(:, :), intent(in) :: m
            real(flyt) :: tr
        end function
        module pure function lo_sqnorm(a) result(nrm)
            real(flyt), dimension(3), intent(in) :: a
            real(flyt) :: nrm
        end function

After the #ifdef block, everything is shifted by 1 level.

I'm on fprettify v0.3.7

flokno commented 1 year ago

Comment: Maybe it's not the preprocessor per se, since apparently there are some checks: https://github.com/pseewald/fprettify/blob/master/fprettify/fparse_utils.py#L35-L46

GSS79 commented 1 year ago

I don't think its related to the directives directly. it is just that when you find a subroutine/module opening you indent afterwards.

we would need to be able to avoid indentation if a new 'region' is open with the same type

pseewald commented 1 year ago

I don't think its related to the directives directly. it is just that when you find a subroutine/module opening you indent afterwards.

I confirm.

we would need to be able to avoid indentation if a new 'region' is open with the same type

I don't think this is general enough, as some of the 'regions' can be nested (e.g. Do, If). I don't see any other way to support this than to parse preprocessor statements, which is not worth it just to get these corner cases right, IMO.

@flokno If you really want to use the preprocessor in this way, and still want you code to be correctly formatted by fprettify, I suggest the following workaround:

#ifdef AGRESSIVE_SANITY
    module function lo_trace(m) result(tr)
#else
        module pure function lo_trace(m) result(tr)
#endif
            real(flyt), dimension(:, :), intent(in) :: m
            real(flyt) :: tr
#ifdef AGRESSIVE_SANITY
        end function
#else
    end function
#endif
flokno commented 1 year ago

ok thanks @pseewald for the workaround