hansec / fortran-language-server

Fortran Language Server for the Language Server Protocol
MIT License
295 stars 57 forks source link

Variables declared within "module procedure" scope lead to duplicates #152

Closed engelfranziska closed 4 years ago

engelfranziska commented 4 years ago

When variables are declared within a "module procedure" scope they seem to remain in the parsers "memory" beyond the "end procedure" statement.

If the same name is used within a subsequent module procedure it is marked as an error (integer :: i in sub2) (duplicate variable), if the same name is used within a subroutine or function (sub3) a warning is displayed on hovering that the variable is going to mask a variable in the parent scope.

module mymod
interface
    module subroutine sub1
    end subroutine
    module subroutine sub2
    end subroutine
end interface
end module

submodule (mymod) submod
contains
    module procedure sub1
        implicit none
        integer :: i
        i = 1
        write(*,*) i
    end procedure

    module procedure sub2
        implicit none
        integer :: i
        i = 2
        write(*,*) i
    end procedure

    module subroutine sub3
        implicit none
        integer :: i
    end subroutine
end submodule

program test
    use mymod
    call sub1
    call sub2
end program

The code works fine and the compiler fails if the declaration of i in `sub2 is removed.

I checked the parse_fortran.py file and as far as I can tell one could either pretend those module procedures are a standalone unit (create a new_scope thingy) or --- which would probably be a more consistent solution --- find a way to connect them to their declaration in the ancestor modules interfaced where "their new scope" might be already declared(?).

I thought about something like this and noticed that I am in way over my head trying to figure this one out.

MODPROC_REGEX = re.compile(r'[ ]*MODULE PROCEDURE[ ]+([a-z0-9_]+)',re.I)
END_MODPROC_WORD = r'PROCEDURE'
...
read_modproc_def ...
    return 'modproc', name
...
elif obj_type = 'modproc'
    #(access scope declared in a different file with parent (sub)module to add local variables)