Mercurial > projects > dil
diff trunk/src/cmd/Statistics.d @ 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 | 33b566df6af4 |
children | ea8c7459f1c4 |
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; +}