Skip to content

Commit b4f435c

Browse files
authored
Merge pull request #800 from barnabasdomozi/cpp_metrics_nested_classes
Add option to skip C++ metrics calculations for lambdas and nested classes
2 parents b756850 + f1a4546 commit b4f435c

File tree

6 files changed

+76
-3
lines changed

6 files changed

+76
-3
lines changed

plugins/cpp/model/include/model/cpprecord.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,21 @@ typedef std::shared_ptr<CppMemberType> CppMemberTypePtr;
4949
#pragma db object
5050
struct CppRecord : CppEntity
5151
{
52+
enum Context {
53+
TOP_LEVEL,
54+
NAMESPACE,
55+
RECORD,
56+
FUNCTION,
57+
OTHER
58+
};
59+
5260
bool isAbstract = false;
5361
bool isPOD = false;
62+
bool isLambda = false;
63+
64+
// Context defines where the CppRecord is located in (e.g. in a namespace).
65+
// Context = RECORD means it is nested within another record.
66+
Context context = Context::OTHER;
5467

5568
std::string toString() const
5669
{
@@ -72,6 +85,18 @@ struct CppRecord : CppEntity
7285

7386
return ret;
7487
}
88+
89+
std::string getContextString() const
90+
{
91+
switch (context)
92+
{
93+
case Context::TOP_LEVEL: return "Top Level";
94+
case Context::NAMESPACE: return "Namespace";
95+
case Context::RECORD: return "Record";
96+
case Context::FUNCTION: return "Function";
97+
case Context::OTHER: return "Other";
98+
}
99+
}
75100
};
76101

77102
typedef std::shared_ptr<CppRecord> CppRecordPtr;

plugins/cpp/parser/src/clangastvisitor.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,20 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor<ClangASTVisitor>
614614
cppRecord->entityHash = astNode->entityHash;
615615
cppRecord->name = rd_->getNameAsString();
616616
cppRecord->qualifiedName = rd_->getQualifiedNameAsString();
617+
cppRecord->isLambda = rd_->isLambda();
618+
619+
const clang::DeclContext* parentDecl = rd_->getParent();
620+
if (parentDecl) {
621+
if (parentDecl->isTranslationUnit()) {
622+
cppRecord->context = model::CppRecord::Context::TOP_LEVEL;
623+
} else if (parentDecl->isNamespace()) {
624+
cppRecord->context = model::CppRecord::Context::NAMESPACE;
625+
} else if (parentDecl->isRecord()) {
626+
cppRecord->context = model::CppRecord::Context::RECORD;
627+
} else if (parentDecl->isFunctionOrMethod()) {
628+
cppRecord->context = model::CppRecord::Context::FUNCTION;
629+
}
630+
}
617631

618632
if (const clang::CXXRecordDecl* crd
619633
= llvm::dyn_cast<clang::CXXRecordDecl>(rd_))

plugins/cpp/service/src/cppservice.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,9 +333,12 @@ void CppServiceHandler::getProperties(
333333
return_["Abstract type"] = "true";
334334
if (type.isPOD)
335335
return_["POD type"] = "true";
336+
if(type.isLambda)
337+
return_["Lambda"] = "true";
336338

337339
return_["Name"] = type.name;
338340
return_["Qualified name"] = type.qualifiedName;
341+
return_["Context"] = type.getContextString();
339342
}
340343
else
341344
LOG(warning)

plugins/cpp/test/src/cpppropertiesservicetest.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ TEST_F(CppPropertiesServiceTest, ClassPropertiesTest)
8686
std::map<std::string, std::string> expected =
8787
{
8888
{"Name", "SimpleClass"},
89+
{"Context", "Namespace"},
8990
{"Qualified name", "cc::test::SimpleClass"}
9091
};
9192

@@ -96,6 +97,7 @@ TEST_F(CppPropertiesServiceTest, ClassPropertiesTest)
9697
std::map<std::string, std::string> expected =
9798
{
9899
{"Name", "NestedClass"},
100+
{"Context", "Namespace"},
99101
{"Qualified name", "cc::test::NestedClass"},
100102
{"POD type", "true"}
101103
};
@@ -107,6 +109,7 @@ TEST_F(CppPropertiesServiceTest, ClassPropertiesTest)
107109
std::map<std::string, std::string> expected =
108110
{
109111
{"Name", "InnerClass"},
112+
{"Context", "Record"},
110113
{"Qualified name", "cc::test::NestedClass::InnerClass"},
111114
{"POD type", "true"}
112115
};
@@ -121,6 +124,7 @@ TEST_F(CppPropertiesServiceTest, InheritancePropertiesTest)
121124
std::map<std::string, std::string> expected =
122125
{
123126
{"Name", "BaseClass1"},
127+
{"Context", "Namespace"},
124128
{"Qualified name", "cc::test::BaseClass1"},
125129
{"Abstract type", "true"}
126130
};
@@ -132,6 +136,7 @@ TEST_F(CppPropertiesServiceTest, InheritancePropertiesTest)
132136
std::map<std::string, std::string> expected =
133137
{
134138
{"Name", "DerivedClass"},
139+
{"Context", "Namespace"},
135140
{"Qualified name", "cc::test::DerivedClass"}
136141
};
137142

plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
#include <model/cppastnodemetrics.h>
88
#include <model/cppastnodemetrics-odb.hxx>
99

10+
#include <model/cppcohesionmetrics.h>
11+
#include <model/cppcohesionmetrics-odb.hxx>
12+
1013
#include <model/cppfunction.h>
1114
#include <model/cppfunction-odb.hxx>
1215

@@ -88,6 +91,8 @@ class CppMetricsParser : public AbstractParser
8891
void relationalCohesionModuleLevel();
8992
// Returns module path query based on parser configuration.
9093
odb::query<model::File> getModulePathsQuery();
94+
// Returns cohesion record query based on parser configuration.
95+
odb::query<model::CohesionCppRecordView> getCohesionRecordQuery();
9196

9297
/// @brief Constructs an ODB query that you can use to filter only
9398
/// the database records of the given parameter type whose path

plugins/cpp_metrics/parser/src/cppmetricsparser.cpp

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -264,13 +264,28 @@ void CppMetricsParser::typeMcCabe()
264264
});
265265
}
266266

267+
odb::query<model::CohesionCppRecordView> CppMetricsParser::getCohesionRecordQuery()
268+
{
269+
odb::query<model::CohesionCppRecordView> query = getFilterPathsQuery<model::CohesionCppRecordView>();
270+
271+
if (_ctx.options.count("cppmetrics-ignore-lambdas")) {
272+
query = query && odb::query<model::CohesionCppRecordView>::CppRecord::isLambda == false;
273+
}
274+
275+
if (_ctx.options.count("cppmetrics-ignore-nested-classes")) {
276+
query = query && odb::query<model::CohesionCppRecordView>::CppRecord::context != model::CppRecord::Context::RECORD;
277+
}
278+
279+
return query;
280+
}
281+
267282
void CppMetricsParser::lackOfCohesion()
268283
{
269284
// Calculate the cohesion metric for all types on parallel threads.
270285
parallelCalcMetric<model::CohesionCppRecordView>(
271286
"Lack of cohesion",
272287
_threadCount * lackOfCohesionPartitionMultiplier, // number of jobs; adjust for granularity
273-
getFilterPathsQuery<model::CohesionCppRecordView>(),
288+
getCohesionRecordQuery(),
274289
[&, this](const MetricsTasks<model::CohesionCppRecordView>& tasks)
275290
{
276291
util::OdbTransaction {_ctx.db} ([&, this]
@@ -376,7 +391,7 @@ void CppMetricsParser::efferentTypeLevel()
376391
parallelCalcMetric<model::CohesionCppRecordView>(
377392
"Efferent coupling of types",
378393
_threadCount * efferentCouplingTypesPartitionMultiplier,// number of jobs; adjust for granularity
379-
getFilterPathsQuery<model::CohesionCppRecordView>(),
394+
getCohesionRecordQuery(),
380395
[&, this](const MetricsTasks<model::CohesionCppRecordView>& tasks)
381396
{
382397
util::OdbTransaction{_ctx.db}([&, this]
@@ -456,7 +471,7 @@ void CppMetricsParser::afferentTypeLevel()
456471
parallelCalcMetric<model::CohesionCppRecordView>(
457472
"Afferent coupling of types",
458473
_threadCount * afferentCouplingTypesPartitionMultiplier,// number of jobs; adjust for granularity
459-
getFilterPathsQuery<model::CohesionCppRecordView>(),
474+
getCohesionRecordQuery(),
460475
[&, this](const MetricsTasks<model::CohesionCppRecordView>& tasks)
461476
{
462477
util::OdbTransaction{_ctx.db}([&, this]
@@ -697,6 +712,12 @@ extern "C"
697712
{
698713
boost::program_options::options_description description("C++ Metrics Plugin");
699714

715+
description.add_options()
716+
("cppmetrics-ignore-lambdas",
717+
"Skip Efferent/Afferent Coupling, Lack of Cohesion C++ metrics calculations for lambdas.")
718+
("cppmetrics-ignore-nested-classes",
719+
"Skip Efferent/Afferent Coupling, Lack of Cohesion C++ metrics calculations for nested classes.");
720+
700721
return description;
701722
}
702723

0 commit comments

Comments
 (0)