Skip to content

Commit

Permalink
New metrics: statement count, max nestedness, lines of code, local va…
Browse files Browse the repository at this point in the history
…riable count.
  • Loading branch information
dbukki committed Apr 4, 2024
1 parent dcb1cc6 commit 8a5610f
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 8 deletions.
39 changes: 39 additions & 0 deletions plugins/cpp/model/include/model/cppfunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ struct CppFunction : CppTypedEntity

unsigned int bumpiness;
unsigned int statementCount;
unsigned int nestedness;

std::string toString() const
{
Expand All @@ -39,6 +40,23 @@ struct CppFunction : CppTypedEntity

typedef std::shared_ptr<CppFunction> CppFunctionPtr;

#pragma db view \
object(CppFunction) \
object(CppAstNode : CppFunction::astNodeId == CppAstNode::id) \
object(File : CppAstNode::location.file)
struct CppFunctionLOC
{
#pragma db column(CppEntity::astNodeId)
CppAstNodeId id;

#pragma db column(CppAstNode::location.range.end.line \
+ "-" + CppAstNode::location.range.start.line)
Position::PosType lines;

#pragma db column(File::path)
std::string filePath;
};

#pragma db view \
object(CppFunction) object(CppVariable = Parameters : CppFunction::parameters)
struct CppFunctionParamCount
Expand Down Expand Up @@ -73,6 +91,24 @@ struct CppFunctionLocalCount
std::size_t count;
};

#pragma db view \
object(CppFunction) \
object(CppVariable = Locals : CppFunction::locals) \
object(CppAstNode : CppFunction::astNodeId == CppAstNode::id) \
object(File : CppAstNode::location.file) \
query((?) + "GROUP BY" + cc::model::CppEntity::astNodeId + "," + cc::model::File::path)
struct CppFunctionLocalCountWithId
{
#pragma db column(CppEntity::astNodeId)
CppAstNodeId id;

#pragma db column("count(" + Locals::id + ")")
std::size_t count;

#pragma db column(File::path)
std::string filePath;
};

#pragma db view \
object(CppFunction) \
object(CppAstNode : CppFunction::astNodeId == CppAstNode::id) \
Expand Down Expand Up @@ -108,6 +144,9 @@ struct CppFunctionBumpyRoad
#pragma db column(CppFunction::statementCount)
unsigned int statementCount;

#pragma db column(CppFunction::nestedness)
unsigned int nestedness;

#pragma db column(File::path)
std::string filePath;
};
Expand Down
8 changes: 8 additions & 0 deletions plugins/cpp/parser/src/clangastvisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,10 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor<ClangASTVisitor>
prevFun->bumpiness += _curFun->bumpiness +
_curFun->statementCount * scope->Depth();
prevFun->statementCount += _curFun->statementCount;

unsigned int nestedness = scope->Depth() + _curFun->nestedness;
if (nestedness > prevFun->nestedness)
prevFun->nestedness = nestedness;
}
}
};
Expand Down Expand Up @@ -315,6 +319,9 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor<ClangASTVisitor>
model::CppFunctionPtr& fun = _functionStack.top();
fun->bumpiness += scope_.Depth();
++fun->statementCount;

if (scope_.Depth() > fun->nestedness)
fun->nestedness = scope_.Depth();
}
}

Expand Down Expand Up @@ -917,6 +924,7 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor<ClangASTVisitor>
cppFunction->flowCount = 0;
cppFunction->bumpiness = 0;
cppFunction->statementCount = 0;
cppFunction->nestedness = 0;

unsigned int count = fn_->getNumTemplateParameterLists();
for (unsigned int t = 0; t < count; ++t)
Expand Down
4 changes: 4 additions & 0 deletions plugins/cpp_metrics/model/include/model/cppastnodemetrics.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ struct CppAstNodeMetrics
BRANCH_COUNT = 6,
LOOP_COUNT = 7,
FLOW_COUNT = 8,
STATEMENT_COUNT = 9,
NESTEDNESS = 10,
LINES_OF_CODE = 11,
LOCAL_COUNT = 12,
};

#pragma db id auto
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,12 @@ class CppMetricsParser : public AbstractParser
virtual bool parse() override;

private:
// Calculate lines of code for every function.
void linesOfCode();
// Calculate the count of parameters for every function.
void functionParameters();
// Calculate the count of local variables for every function.
void functionLocals();
// Calculate the McCabe complexity of functions.
void functionMcCabe();
// Calculate the bumpy road metric for every function.
Expand Down
75 changes: 67 additions & 8 deletions plugins/cpp_metrics/parser/src/cppmetricsparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,27 @@ bool CppMetricsParser::cleanupDatabase()
return true;
}


void CppMetricsParser::linesOfCode()
{
util::OdbTransaction {_ctx.db} ([&, this]
{
for (const model::CppFunctionLOC& loc
: _ctx.db->query<model::CppFunctionLOC>())
{
// Skip functions that were included from external libraries.
if (!cc::util::isRootedUnderAnyOf(_inputPaths, loc.filePath))
continue;

model::CppAstNodeMetrics metric;
metric.astNodeId = loc.id;
metric.type = model::CppAstNodeMetrics::Type::LINES_OF_CODE;
metric.value = loc.lines;
_ctx.db->persist(metric);
}
});
}

void CppMetricsParser::functionParameters()
{
util::OdbTransaction {_ctx.db} ([&, this]
Expand All @@ -123,6 +144,26 @@ void CppMetricsParser::functionParameters()
});
}

void CppMetricsParser::functionLocals()
{
util::OdbTransaction {_ctx.db} ([&, this]
{
for (const model::CppFunctionLocalCountWithId& localCount
: _ctx.db->query<model::CppFunctionLocalCountWithId>())
{
// Skip functions that were included from external libraries.
if (!cc::util::isRootedUnderAnyOf(_inputPaths, localCount.filePath))
continue;

model::CppAstNodeMetrics funcLocals;
funcLocals.astNodeId = localCount.id;
funcLocals.type = model::CppAstNodeMetrics::Type::LOCAL_COUNT;
funcLocals.value = localCount.count;
_ctx.db->persist(funcLocals);
}
});
}

void CppMetricsParser::functionMcCabe()
{
util::OdbTransaction {_ctx.db} ([&, this]
Expand Down Expand Up @@ -182,11 +223,23 @@ void CppMetricsParser::functionBumpyRoad()
const double dC = function.statementCount;
const bool empty = function.statementCount == 0;

model::CppAstNodeMetrics metrics;
metrics.astNodeId = function.astNodeId;
metrics.type = model::CppAstNodeMetrics::Type::BUMPY_ROAD;
metrics.value = empty ? 1.0 : (dB / dC);
_ctx.db->persist(metrics);
model::CppAstNodeMetrics br;
br.astNodeId = function.astNodeId;
br.type = model::CppAstNodeMetrics::Type::BUMPY_ROAD;
br.value = empty ? 1.0 : (dB / dC);
_ctx.db->persist(br);

model::CppAstNodeMetrics sc;
sc.astNodeId = function.astNodeId;
sc.type = model::CppAstNodeMetrics::Type::STATEMENT_COUNT;
sc.value = function.statementCount;
_ctx.db->persist(sc);

model::CppAstNodeMetrics nn;
nn.astNodeId = function.astNodeId;
nn.type = model::CppAstNodeMetrics::Type::NESTEDNESS;
nn.value = function.nestedness;
_ctx.db->persist(nn);
}
});
}
Expand Down Expand Up @@ -437,7 +490,9 @@ class MetricsExtractor

bool CppMetricsParser::parse()
{
linesOfCode();
//functionParameters();
functionLocals();
functionMcCabe();
functionBumpyRoad();
//lackOfCohesion();
Expand Down Expand Up @@ -466,11 +521,15 @@ bool CppMetricsParser::extract()
std::cout << "Extracting to: " << me.RootDir().c_str() << std::endl;

typedef model::CppAstNodeMetrics::Type Type;
me.Extract(Type::BRANCH_COUNT, "Branch");
me.Extract(Type::LOOP_COUNT, "Loop");
me.Extract(Type::FLOW_COUNT, "Flow");
me.Extract(Type::BRANCH_COUNT, "BranchCount");
me.Extract(Type::LOOP_COUNT, "LoopCount");
me.Extract(Type::FLOW_COUNT, "FlowCount");
me.Extract(Type::MCCABE, "McCabe");
me.Extract(Type::BUMPY_ROAD, "BumpyRoad");
me.Extract(Type::STATEMENT_COUNT, "StatementCount");
me.Extract(Type::NESTEDNESS, "Nestedness");
me.Extract(Type::LINES_OF_CODE, "LinesOfCode");
me.Extract(Type::LOCAL_COUNT, "LocalCount");

return true;
}
Expand Down

0 comments on commit 8a5610f

Please sign in to comment.