fdoc

filefdoc_stats.f90

Contents

fdoc_statsprivate

The size of source files: how many lines hold code, comments or nothing. This uses fformat's tokens, so that a ! in a string is not taken for a comment. It runs in parallel, so nothing here calls a function returning a deferred-length string (see example/slen_race.f90).

Source

module fdoc_stats
!! The size of source files: how many lines hold code, comments or nothing. This uses fformat's tokens,
!! so that a `!` in a string is not taken for a comment. It runs in parallel, so nothing here calls a
!! function returning a deferred-length string (see `example/slen_race.f90`).
use iso_fortran_env, only: int64
use ffmt_tokens, only: token_list_t, TK_SPACE, TK_NEWLINE, TK_COMMENT, TK_BOM
use ffmt_lexer, only: tokenize
implicit none
private

public :: file_stats_t, count_source, add_stats

type :: file_stats_t
    !! The size of a source file, or of several.
    integer :: lines = 0                !! all lines
    integer :: code = 0                 !! lines with code, which may also have a comment
    integer :: comments = 0             !! lines with only a comment
    integer :: blank = 0                !! lines with nothing
    integer :: procedures = 0           !! procedures defined in it
    integer(int64) :: bytes = 0         !! its size
end type file_stats_t

contains

!> Count the lines of `text`. A last line with no line ending counts as a line.
subroutine count_source(text, stats)
    character(len=*), intent(in) :: text    !! the source
    type(file_stats_t), intent(inout) :: stats  !! where the counts go
    type(token_list_t) :: tokens
    logical :: code, comment, open
    integer :: k

    stats%bytes = len(text, int64)
    call tokenize(text, tokens)
    code = .false.
    comment = .false.
    open = .false.
    do k = 1, tokens%n
        select case (tokens%tok(k)%kind)
        case (TK_NEWLINE)
            call end_line()
            cycle
        case (TK_COMMENT)
            comment = .true.
        case (TK_SPACE, TK_BOM)
            continue
        case default
            code = .true.
        end select
        open = .true.
    end do
    if (open) call end_line()

contains

    !> Count the line that ends here.
    subroutine end_line()

        stats%lines = stats%lines + 1
        if (code) then
            stats%code = stats%code + 1
        else if (comment) then
            stats%comments = stats%comments + 1
        else
            stats%blank = stats%blank + 1
        end if
        code = .false.
        comment = .false.
        open = .false.
    end subroutine end_line

end subroutine count_source

!> Add the counts of `item` to `total`.
pure subroutine add_stats(total, item)
    type(file_stats_t), intent(inout) :: total  !! the total
    type(file_stats_t), intent(in) :: item      !! what to add

    total%lines = total%lines + item%lines
    total%code = total%code + item%code
    total%comments = total%comments + item%comments
    total%blank = total%blank + item%blank
    total%procedures = total%procedures + item%procedures
    total%bytes = total%bytes + item%bytes
end subroutine add_stats

end module fdoc_stats

Graphs

Files that depend on this one