class CLASS_STATISTICS
Obtains code word count and byte count of Eiffel class source. Code words include keywords, identifier words and quoted strings, but exclude comments and indexing notes.
note
description: "[
Obtains code word count and byte count of Eiffel class source.
Code words include keywords, identifier words and quoted strings,
but exclude comments and indexing notes.
]"
author: "Finnian Reilly"
copyright: "Copyright (c) 2001-2017 Finnian Reilly"
contact: "finnian at eiffel hyphen loop dot com"
license: "MIT license (See: en.wikipedia.org/wiki/MIT_License)"
date: "2020-05-07 11:03:54 GMT (Thursday 7th May 2020)"
revision: "7"
class
CLASS_STATISTICS
inherit
CLASS_STATISTICS_I
EL_PLAIN_TEXT_LINE_STATE_MACHINE
rename
make as make_machine
end
create
make_from_source, make_from_file
feature {NONE} -- Initialization
make (a_file_size, a_word_count: INTEGER)
do
make_machine
file_size := a_file_size; word_count := a_word_count
end
make_from_file (source_path: EL_FILE_PATH)
do
make_machine
if attached open_lines (source_path, Latin_1) as source_lines then
file_size := source_lines.byte_count
do_once_with_file_lines (agent count_words, source_lines)
end
end
make_from_source (source: ZSTRING; a_file_size: INTEGER)
local
lines: EL_SPLIT_ZSTRING_LIST; index: INTEGER
do
file_size := a_file_size
index := source.substring_index (New_line, 1)
create lines.make (source, New_line)
do_with_split_list (agent count_words, lines, False)
end
feature {NONE} -- Line state handlers
count_words (line: ZSTRING)
local
l_keyword, l_line: ZSTRING; comment_index: INTEGER
do
l_keyword := leftmost_keyword (line)
if Indexing_keywords.has (l_keyword) then
state := agent find_class_code
else
if Keyword_feature /~ l_keyword then
comment_index := line.substring_index (Comment_marker, 1)
if comment_index > 0 then
l_line := line.substring (1, comment_index - 1)
else
l_line := line
end
word_count := word_count + line_word_count (l_line)
end
end
end
find_class_code (line: ZSTRING)
do
if Code_start_keywords.has (leftmost_keyword (line)) then
state := agent count_words
count_words (line)
end
end
feature {NONE} -- Implementation
leftmost_keyword (line: ZSTRING): ZSTRING
-- keyword with no whitespace preceding it
local
i: INTEGER; appending: BOOLEAN
do
create Result.make (10)
appending := True
from i := 1 until not appending or else i > line.count loop
if line.is_alpha_item (i) then
Result.append_z_code (line.z_code (i))
else
appending := False
end
i := i + 1
end
end
line_word_count (line: ZSTRING): INTEGER
local
i: INTEGER; appending: BOOLEAN
do
from i := 1 until i > line.count loop
if appending then
if not line.is_alpha_numeric_item (i) then
appending := False
end
else
if line.is_alpha_numeric_item (i) then
appending := True
Result := Result + 1
end
end
i := i + 1
end
end
feature {NONE} -- Constants
Code_start_keywords: ARRAY [ZSTRING]
once
Result := << "frozen", "deferred", "class", "end", "feature" >>
Result.compare_objects
end
Comment_marker: ZSTRING
once
Result := "--"
end
Indexing_keywords: ARRAY [ZSTRING]
once
Result := << "note", ";note", "indexing" >>
-- ;note is frequently seen in Eiffel Software code
Result.compare_objects
end
Keyword_feature: ZSTRING
once
Result := "feature"
end
New_line: ZSTRING
once
Result := "%N"
end
end