Mercurial > projects > dil
changeset 401:fcdf7ac5ad27
Improved statistics generation.
Now multiple files can be passed to the stats/statistics command.
Whitespace characters are counted correctly as well.
author | Aziz K?ksal <aziz.koeksal@gmail.com> |
---|---|
date | Sat, 22 Sep 2007 19:49:54 +0200 |
parents | a0fa0dcfa50a |
children | 22d65b2bef4f |
files | trunk/src/cmd/Statistics.d trunk/src/main.d |
diffstat | 2 files changed, 108 insertions(+), 24 deletions(-) [+] |
line wrap: on
line diff
--- a/trunk/src/cmd/Statistics.d Sat Sep 22 18:24:54 2007 +0200 +++ b/trunk/src/cmd/Statistics.d Sat Sep 22 19:49:54 2007 +0200 @@ -16,27 +16,91 @@ uint identCount; uint numberCount; uint commentCount; + uint linesOfCode; + + void opAddAssign(Statistics s) + { + this.whitespaceCount += s.whitespaceCount; + this.wsTokenCount += s.wsTokenCount; + this.keywordCount += s.keywordCount; + this.identCount += s.identCount; + this.numberCount += s.numberCount; + this.commentCount += s.commentCount; + this.linesOfCode += s.linesOfCode; + } } -void execute(string fileName) +void execute(string[] filePaths) { - auto sourceText = loadFile(fileName); - auto lx = new Lexer(sourceText, fileName); + Statistics[] stats; + foreach (filePath; filePaths) + stats ~= getStatistics(filePath); + + Statistics total; + + foreach (i, ref stat; stats) + { + total += stat; + Stdout.formatln( + "----\n" + "File: {0}\n" + "Whitespace character count: {1}\n" + "Whitespace token count: {2}\n" + "Keyword count: {3}\n" + "Identifier count: {4}\n" + "Number count: {5}\n" + "Comment count: {6}\n" + "Lines of code: {7}", + filePaths[i], + stat.whitespaceCount, + stat.wsTokenCount, + stat.keywordCount, + stat.identCount, + stat.numberCount, + stat.commentCount, + stat.linesOfCode + ); + } + + if (filePaths.length > 1) + Stdout.formatln( + "--------------------------------------------------------------------------------\n" + "Total:\n" + "Whitespace character count: {0}\n" + "Whitespace token count: {1}\n" + "Keyword count: {2}\n" + "Identifier count: {3}\n" + "Number count: {4}\n" + "Comment count: {5}\n" + "Lines of code: {6}", + total.whitespaceCount, + total.wsTokenCount, + total.keywordCount, + total.identCount, + total.numberCount, + total.commentCount, + total.linesOfCode + ); +} + +Statistics getStatistics(string filePath) +{ + auto sourceText = loadFile(filePath); + auto lx = new Lexer(sourceText, filePath); auto token = lx.getTokens(); Statistics stats; + + stats.linesOfCode = lx.loc; // Traverse linked list. while (token.type != TOK.EOF) { token = token.next; // Count whitespace characters - if (token.ws) - { - // TODO: naive method doesn't account for \r\n, LS and PS. - stats.whitespaceCount += token.start - token.ws; - } + if (token.ws !is null) + stats.whitespaceCount += countWhitespaceCharacters(token.ws, token.start); switch (token.type) { @@ -59,19 +123,39 @@ if (token.isWhitespace) stats.wsTokenCount++; } - Stdout.formatln( - "Whitespace character count: {0}\n" - "Whitespace token count: {1}\n" - "Keyword count: {2}\n" - "Identifier count: {3}\n" - "Number count: {4}\n" - "Comment count: {5}\n" - "Lines of code: {6}", - stats.whitespaceCount, - stats.wsTokenCount, - stats.keywordCount, - stats.identCount, - stats.numberCount, - stats.commentCount, - lx.loc); + return stats; } + +/// Counts newlines, \t, \v, \f and ' ' as whitespace characters. +uint countWhitespaceCharacters(char* p, char* end) +{ + uint count; +Loop: + while (1) + { + switch (*p) + { + case '\r': + if (p[1] == '\n') + ++p; + case '\n': + ++p; + ++count; + break; + case LS[0]: + if (p[1] == LS[1] && (p[2] == LS[2] || p[2] == PS[2])) + { + p += 3; + ++count; + break; + } + default: + if (!dil.Lexer.isspace(*p)) + break Loop; // Exit loop. + ++p; + ++count; + } + } + assert(p is end); + return count; +}
--- a/trunk/src/main.d Sat Sep 22 18:24:54 2007 +0200 +++ b/trunk/src/main.d Sat Sep 22 19:49:54 2007 +0200 @@ -88,7 +88,7 @@ cmd.ImportGraph.execute(filePath, includePaths, regexps, levels, options); break; case "stats", "statistics": - cmd.Statistics.execute(args[2]); + cmd.Statistics.execute(args[2..$]); break; case "parse": if (args.length == 3)