D-Scanner/src/dscanner/analysis/stats_collector.d

159 lines
4.3 KiB
D

// Copyright Brian Schott (Hackerpilot) 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module dscanner.analysis.stats_collector;
import dscanner.analysis.base;
extern (C++) class StatsCollector(AST) : BaseAnalyzerDmd
{
alias visit = BaseAnalyzerDmd.visit;
mixin AnalyzerInfo!"stats_collector";
public uint interfaceCount;
public uint classCount;
public uint functionCount;
public uint templateCount;
public uint structCount;
public uint statementCount;
// TODO: Count lines of code
public uint lineOfCodeCount;
// TODO: Count undocumented public symbols
public uint undocumentedPublicSymbols;
extern (D) this(string fileName = "", bool skipTests = false)
{
super(fileName, skipTests);
}
override void visit(AST.InterfaceDeclaration interfaceDecl)
{
interfaceCount++;
super.visit(interfaceDecl);
}
override void visit(AST.ClassDeclaration classDecl)
{
classCount++;
super.visit(classDecl);
}
override void visit(AST.FuncDeclaration funcDecl)
{
functionCount++;
super.visit(funcDecl);
}
override void visit(AST.TemplateDeclaration templateDecl)
{
templateCount++;
super.visit(templateDecl);
}
override void visit(AST.StructDeclaration structDecl)
{
structCount++;
super.visit(structDecl);
}
mixin VisitStatement!(AST.ErrorStatement);
mixin VisitStatement!(AST.PeelStatement);
mixin VisitStatement!(AST.ScopeStatement);
mixin VisitStatement!(AST.ExpStatement);
mixin VisitStatement!(AST.ReturnStatement);
mixin VisitStatement!(AST.IfStatement);
mixin VisitStatement!(AST.CaseStatement);
mixin VisitStatement!(AST.DefaultStatement);
mixin VisitStatement!(AST.LabelStatement);
mixin VisitStatement!(AST.GotoStatement);
mixin VisitStatement!(AST.GotoDefaultStatement);
mixin VisitStatement!(AST.GotoCaseStatement);
mixin VisitStatement!(AST.BreakStatement);
mixin VisitStatement!(AST.DtorExpStatement);
mixin VisitStatement!(AST.MixinStatement);
mixin VisitStatement!(AST.ForwardingStatement);
mixin VisitStatement!(AST.DoStatement);
mixin VisitStatement!(AST.WhileStatement);
mixin VisitStatement!(AST.ForStatement);
mixin VisitStatement!(AST.ForeachStatement);
mixin VisitStatement!(AST.SwitchStatement);
mixin VisitStatement!(AST.ContinueStatement);
mixin VisitStatement!(AST.WithStatement);
mixin VisitStatement!(AST.TryCatchStatement);
mixin VisitStatement!(AST.ThrowStatement);
mixin VisitStatement!(AST.DebugStatement);
mixin VisitStatement!(AST.TryFinallyStatement);
mixin VisitStatement!(AST.ScopeGuardStatement);
mixin VisitStatement!(AST.SwitchErrorStatement);
mixin VisitStatement!(AST.UnrolledLoopStatement);
mixin VisitStatement!(AST.ForeachRangeStatement);
mixin VisitStatement!(AST.CompoundDeclarationStatement);
mixin VisitStatement!(AST.CompoundAsmStatement);
mixin VisitStatement!(AST.StaticAssertStatement);
mixin VisitStatement!(AST.CaseRangeStatement);
mixin VisitStatement!(AST.SynchronizedStatement);
mixin VisitStatement!(AST.AsmStatement);
mixin VisitStatement!(AST.InlineAsmStatement);
mixin VisitStatement!(AST.GccAsmStatement);
mixin VisitStatement!(AST.ImportStatement);
private template VisitStatement(NodeType)
{
override void visit(NodeType node)
{
statementCount++;
super.visit(node);
}
}
}
unittest
{
import std.file : exists, remove;
import std.path : dirName;
import std.stdio : File, stderr;
import dscanner.analysis.rundmd : parseDmdModule;
import dmd.astcodegen : ASTCodegen;
string code = q{
interface I {}
class C {}
void f() {}
template T() {}
struct S {}
void funcWithStatements()
{
int a = 1;
if (a == 1)
a = 2;
a++;
}
}c;
auto testFileName = "test.d";
File f = File(testFileName, "w");
scope(exit)
{
assert(exists(testFileName));
remove(testFileName);
}
f.rawWrite(code);
f.close();
auto dmdModule = parseDmdModule(testFileName, code);
auto collector = new StatsCollector!ASTCodegen();
dmdModule.accept(collector);
assert(collector.interfaceCount == 1);
assert(collector.classCount == 1);
assert(collector.functionCount == 2);
assert(collector.templateCount == 1);
assert(collector.structCount == 1);
assert(collector.statementCount == 4);
stderr.writeln("Unittest for StatsCollector passed.");
}