From 7681d4e87c9b936e088ce6005f35e2862e010300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Cser=C3=A9p?= Date: Mon, 29 Apr 2024 13:26:35 +0200 Subject: [PATCH 01/15] Build CodeCompass in Release mode in CI --- .github/workflows/ci.yml | 2 +- .github/workflows/codeql.yml | 2 +- .gitlab/build-codecompass.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7989a3090..346b2d262 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,7 @@ name: Build project on: [push, pull_request, workflow_dispatch] env: - BUILD_TYPE: Debug + BUILD_TYPE: RelWithDebInfo ## For locally compiled dependencies INSTALL_PATH: ${{github.workspace}}/dependencies/install ## Temp directory for installers of the downloaded dependencies diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 85a08bc94..ece93bf67 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -41,7 +41,7 @@ jobs: analyze-cpp: name: Analyze C-C++ env: - BUILD_TYPE: Debug + BUILD_TYPE: RelWithDebInfo INSTALL_PATH: ${{github.workspace}}/dependencies/install DOWNLOAD_PATH: ${{github.workspace}}/dependencies/download runs-on: ubuntu-22.04 diff --git a/.gitlab/build-codecompass.sh b/.gitlab/build-codecompass.sh index 512b292a6..87ca961ad 100644 --- a/.gitlab/build-codecompass.sh +++ b/.gitlab/build-codecompass.sh @@ -63,7 +63,7 @@ cd $CC_BUILD_DIR cmake $CC_SRC_DIR \ -DCMAKE_INSTALL_PREFIX=$CC_INSTALL_DIR \ -DDATABASE=pgsql \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DCMAKE_BUILD_TYPE=Release \ -DWITH_AUTH="plain;ldap" \ -DLLVM_DIR=$DEPS_INSTALL_RUNTIME_DIR/llvm/lib/cmake/llvm/ \ -DClang_DIR=$DEPS_INSTALL_RUNTIME_DIR/llvm/lib/cmake/clang/ From 3c853e386b42cf25a343ab40afc3647abf4b14f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Cser=C3=A9p?= Date: Wed, 1 May 2024 07:15:03 +0200 Subject: [PATCH 02/15] Log the start of each C++ metric computation --- plugins/cpp_metrics/parser/src/cppmetricsparser.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp index 12ebd1cb7..eace3bfc6 100644 --- a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp +++ b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp @@ -272,9 +272,13 @@ void CppMetricsParser::lackOfCohesion() bool CppMetricsParser::parse() { + LOG(info) << "[cppmetricsparser] Computing function parameter count metric."; functionParameters(); + LOG(info) << "[cppmetricsparser] Computing McCabe metric for functions."; functionMcCabe(); + LOG(info) << "[cppmetricsparser] Computing Bumpy Road metric for functions."; functionBumpyRoad(); + LOG(info) << "[cppmetricsparser] Computing Lack of Cohesion metric for types."; lackOfCohesion(); return true; } From 7536c0a8a8c9fb36a8bc92342c990f711fb20df5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Cser=C3=A9p?= Date: Wed, 1 May 2024 07:18:17 +0200 Subject: [PATCH 03/15] Print debug info upon successful completion of TU parsing --- plugins/cpp/parser/src/cppparser.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/cpp/parser/src/cppparser.cpp b/plugins/cpp/parser/src/cppparser.cpp index 16ae1d6c0..58620801c 100644 --- a/plugins/cpp/parser/src/cppparser.cpp +++ b/plugins/cpp/parser/src/cppparser.cpp @@ -779,6 +779,10 @@ bool CppParser::parseByJson( LOG(warning) << '(' << job_.index << '/' << numCompileCommands << ')' << " Parsing " << command.Filename << " has been failed."; + else + LOG(debug) + << '(' << job_.index << '/' << numCompileCommands << ')' + << " Parsing " << command.Filename << " finished successfully."; }); //--- Push all commands into the thread pool's queue ---// From 613ee04f9b9c60f2d958a5ee1e92a056e464af0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Cser=C3=A9p?= Date: Tue, 30 Apr 2024 08:30:35 +0200 Subject: [PATCH 04/15] Update Tarball generation for Ubuntu 20.04 Focal Fossa. NodeJS v18 is not compatible with Ubuntu 16.04, due to the GLIBC mismatch. --- .gitlab/build-deps.sh | 8 ++--- .gitlab/ci.yml | 79 +++++-------------------------------------- 2 files changed, 12 insertions(+), 75 deletions(-) diff --git a/.gitlab/build-deps.sh b/.gitlab/build-deps.sh index 1701860d4..09db12e0d 100644 --- a/.gitlab/build-deps.sh +++ b/.gitlab/build-deps.sh @@ -373,12 +373,12 @@ rm -f $PACKAGES_DIR/release-1.10.0.tar.gz ####### cd $PACKAGES_DIR -wget --no-verbose --no-clobber https://nodejs.org/dist/v16.20.2/node-v16.20.2-linux-x64.tar.xz -tar -xf node-v16.20.2-linux-x64.tar.xz -C $DEPS_INSTALL_RUNTIME_DIR -rm -f node-v16.20.2-linux-x64.tar.xz +wget --no-verbose --no-clobber https://nodejs.org/dist/v18.20.2/node-v18.20.2-linux-x64.tar.xz +tar -xf node-v18.20.2-linux-x64.tar.xz -C $DEPS_INSTALL_RUNTIME_DIR +rm -f node-v18.20.2-linux-x64.tar.xz cd $DEPS_INSTALL_RUNTIME_DIR -mv node-v16.20.2-linux-x64 node-install +mv node-v18.20.2-linux-x64 node-install export PATH=$DEPS_INSTALL_RUNTIME_DIR/node-install/bin:$PATH ############ diff --git a/.gitlab/ci.yml b/.gitlab/ci.yml index acb3e8f45..625890def 100644 --- a/.gitlab/ci.yml +++ b/.gitlab/ci.yml @@ -61,65 +61,16 @@ variables: echo "GLIBC version: $GLIBC_VERSION" echo "GLIBCXX versions: $GLIBCXX_VERSIONS" -tarball suse-15: +tarball ubuntu-20.04: extends: .tarball - image: opensuse/leap:15 + image: ubuntu:20.04 cache: - key: "leap" + key: "focal" variables: GCC_VERSION: 9.3.0 ODB_VERSION: 2.5.0 - before_script: - - zypper refresh - - zypper update -y - # download tools - - zypper install -y curl wget gzip bzip2 unzip ca-certificates - # build tools for CodeCompass - - zypper install -y -t pattern devel_basis - - zypper install -y binutils gcc-c++ gmp-devel - # build tools for OpenLDAP - - zypper install -y groff - # build tools for ccdb-tools - - zypper install -y libffi-devel - # show GLIBC verison - - *show-glibc-version - -# Permanently disabled job -# (Distribution package repository metadata not available anymore.) -.tarball suse-42.1: - extends: .tarball - image: opensuse/archive:42.1 - cache: - key: "malachite" - variables: - GCC_VERSION: 5.5.0 - ODB_VERSION: 2.4.0 - before_script: - - zypper refresh - - zypper update -y - # download tools - - zypper install -y curl wget gzip bzip2 unzip ca-certificates - # build tools for CodeCompass - - zypper install -y -t pattern devel_basis - - zypper install -y binutils gcc-c++ gmp-devel - # build tools for OpenLDAP - - zypper install -y groff - # build tools for ccdb-tools - - zypper install -y libffi-devel - # disable SSL certificate check (distribution's cacert is outdated) - - echo "check_certificate = off" >> /etc/wgetrc - - echo insecure >> ~/.curlrc - # show GLIBC verison - - *show-glibc-version - -tarball ubuntu-16.04: - extends: .tarball - image: ubuntu:16.04 - cache: - key: "xenial" - variables: - GCC_VERSION: 5.5.0 - ODB_VERSION: 2.4.0 + # No interactive timezone dialog for tzdata + DEBIAN_FRONTEND: noninteractive before_script: - apt-get update -yqq # download tools @@ -154,22 +105,8 @@ tarball ubuntu-16.04: - scp -P22 build/codecompass.tar.gz gitlab-deployer@codecompass.net:/var/www/codecompass/$FILENAME - ssh -p22 gitlab-deployer@codecompass.net "mv -f /var/www/codecompass/$FILENAME /var/www/codecompass/live/wwwroot/tarball/$FILENAME" -upload suse-15: - extends: .upload - variables: - ARCH_SUFFIX: suse-15 - needs: ["tarball suse-15"] - -# Permanently disabled job -# (Distribution package repository metadata not available anymore.) -.upload suse-42.1: - extends: .upload - variables: - ARCH_SUFFIX: suse-42.1 - needs: ["tarball suse-42.1"] - -upload ubuntu-16.04: +upload ubuntu-20.04: extends: .upload variables: - ARCH_SUFFIX: ubuntu-16.04 - needs: ["tarball ubuntu-16.04"] + ARCH_SUFFIX: ubuntu-20.04 + needs: ["tarball ubuntu-20.04"] From 0299025f9dd5672f5d60ffe21b0de040f060b46e Mon Sep 17 00:00:00 2001 From: Klein Kristof Date: Wed, 8 May 2024 09:59:50 +0200 Subject: [PATCH 05/15] Added calculation for relational cohesion --- plugins/cpp_metrics/model/CMakeLists.txt | 5 +- .../include/model/cpprelationalcohesion.h | 111 ++++++++++ .../cppmetricsparser/cppmetricsparser.h | 2 + .../parser/src/cppmetricsparser.cpp | 205 ++++++++++++++++++ 4 files changed, 321 insertions(+), 2 deletions(-) create mode 100644 plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h diff --git a/plugins/cpp_metrics/model/CMakeLists.txt b/plugins/cpp_metrics/model/CMakeLists.txt index 38d8ca343..580be0d66 100644 --- a/plugins/cpp_metrics/model/CMakeLists.txt +++ b/plugins/cpp_metrics/model/CMakeLists.txt @@ -5,11 +5,12 @@ include_directories( set(ODB_SOURCES include/model/cppastnodemetrics.h include/model/cppcohesionmetrics.h - include/model/cppfilemetrics.h) + include/model/cppfilemetrics.h + include/model/cpprelationalcohesion.h) generate_odb_files("${ODB_SOURCES}" "cpp") add_odb_library(cppmetricsmodel ${ODB_CXX_SOURCES}) target_link_libraries(cppmetricsmodel cppmodel) -install_sql() \ No newline at end of file +install_sql() diff --git a/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h b/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h new file mode 100644 index 000000000..654cd3f7f --- /dev/null +++ b/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h @@ -0,0 +1,111 @@ +#ifndef CC_MODEL_CPPRELATIONALCOHESION_H +#define CC_MODEL_CPPRELATIONALCOHESION_H + +#include +#include +#include +#include +#include + +namespace cc +{ + namespace model + { + + #pragma db view \ + object(File) + struct RelationalCohesionFileView + { + #pragma db column(File::path) + std::string filePath; + + #pragma db column(File::type) + std::string fileType; + + }; + + #pragma db view \ + object(CppRecord) \ + object(CppAstNode : CppRecord::astNodeId == CppAstNode::id) \ + object(File : CppAstNode::location.file) \ + object(CppMemberType : CppMemberType::memberAstNode) + struct RelationalCohesionRecordView + { + #pragma db column(CppEntity::entityHash) + std::size_t entityHash; + + #pragma db column(CppMemberType::typeHash) + std::size_t typeHash; + + #pragma db column(CppEntity::qualifiedName) + std::string qualifiedName; + + #pragma db column(CppEntity::astNodeId) + CppAstNodeId astNodeId; + + #pragma db column(File::path) + std::string filePath; + }; + + #pragma db view \ + object(CppFunction) \ + object(CppAstNode : CppFunction::astNodeId == CppAstNode::id) \ + object(File : CppAstNode::location.file) + struct RelationalCohesionFunctionView + { + #pragma db column(CppEntity::entityHash) + std::size_t entityHash; + + #pragma db column(CppTypedEntity::typeHash) + std::size_t returnType; + + #pragma db column(File::path) + std::string filePath; + }; + + #pragma db view \ + object(CppEntity) \ + object(CppVariable = Parameters : CppFunction::parameters) \ + object(CppAstNode : CppAstNode.id == CppEntity.astNodeId) \ + object(File : CppAstNode::location.file) + struct RelationalCohessionFunctionParameterView + { + #pragma db column(Parameters::typeHash) + std::size_t typeHash; + + #pragma db column(File::path) + std::string filePath; + }; + + + #pragma db view \ + object(CppVariable = Locals : CppFunction::locals) \ + object(CppAstNode : CppAstNode.id == CppEntity.astNodeId) \ + object(File : CppAstNode::location.file) + struct RelationalCohessionFunctionLocalView + { + #pragma db column(Locals::typeHash) + std::size_t typeHash; + + #pragma db column(File::path) + std::string filePath; + }; + + #pragma db view \ + object(CppVariable) \ + object(CppAstNode : CppAstNode.id == CppEntity.astNodeId) \ + object(File : CppAstNode::location.file) + struct RelationalCohesionVariableView + { + #pragma db column(CppVariable::typeHash) + std::size_t typeHash; + + #pragma db column(File::path) + std::string filePath; + + }; + + } +} + +#endif \ No newline at end of file diff --git a/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h b/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h index 6dcfb0bc2..e376f467c 100644 --- a/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h +++ b/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h @@ -38,6 +38,8 @@ class CppMetricsParser : public AbstractParser // Calculate the lack of cohesion between member variables // and member functions for every type. void lackOfCohesion(); + // Calculate the cohesion within modules + void relationalCohesion(); std::vector _inputPaths; std::unordered_set _fileIdCache; diff --git a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp index 7e8269a4d..3a71529c6 100644 --- a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp +++ b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include @@ -18,6 +20,7 @@ #include #include +#include namespace cc { @@ -141,6 +144,208 @@ void CppMetricsParser::functionMcCabe() }); } +void CppMetricsParser::relationalCohesion() +{ + util::OdbTransaction {_ctx.db} ([&, this] + { + + std::unordered_set filepaths; + std::vector filepathVector; + filepathVector.insert(filepathVector.end(), filepaths.begin(), filepaths.end()); + std::unordered_map> pathsInModule; + std::unordered_map> typesUnderPath; + std::unordered_map> functionsUnderPath; + std::unordered_map typeDefinitionPaths; + + //get the project filepaths + //change this later to only get the required modules + for (const model::RelationalCohesionFileView& file + : _ctx.db->query()) + { + if (cc::util::isRootedUnderAnyOf( _inputPaths, file.filePath) && + file.fileType == "DIR") + { + filepaths.insert(file.filePath); + } + } + + //get what filepaths are contained within a module + for (auto &¤tPath : filepaths) + { + std::vector pathVector; + pathVector.push_back(currentPath); + std::unordered_set pathsFound; + for (auto &&path : filepaths) + { + if (cc::util::isRootedUnderAnyOf(pathVector,path)) + { + pathsFound.insert(path); + } + } + pathsInModule.insert(std::make_pair(currentPath,pathsFound)); + } + + //find types defined under every filepath in the project + for (auto &¤tPath : filepaths) + { + std::unordered_set typesFound; + std::vector pathVector; + pathVector.push_back(currentPath); + for (const model::RelationalCohesionRecordView& record + : _ctx.db->query()) + { + if (cc::util::isRootedUnderAnyOf(pathVector,record.filePath)) + { + typesFound.insert(record.typeHash); + } + } + typesUnderPath.insert(std::make_pair(currentPath,typesFound)); + } + + //save where each type is defined so self relations can be excluded + for (const model::RelationalCohesionRecordView& record + : _ctx.db->query()) + { + typeDefinitionPaths.insert(std::make_pair(record.typeHash,record.filePath)); + } + + //find relations + for (auto &&path : filepaths) + { + std::vector currentModulePaths( + pathsInModule[path].begin(), pathsInModule[path].end() + ); + + uint relationsInModule = 0; //R + std::unordered_set relationsInCurrentFile; + std::unordered_set filesAlreadyChecked; + //select the next module + for (auto &&modulePath : currentModulePaths) + { + std::vector pathVector; + pathVector.push_back(modulePath); + //find the files defined under the current module member + for (const model::RelationalCohesionFileView& file + : _ctx.db->query()) + { + if (file.fileType != "CPP" && + !cc::util::isRootedUnderAnyOf(pathVector,file.filePath) && + filesAlreadyChecked.find(file.filePath) != filesAlreadyChecked.end() + ) + { + continue; + } + filesAlreadyChecked.insert(file.filePath); + relationsInCurrentFile.clear(); + //check function return types + for (const model::RelationalCohesionFunctionView& function + : _ctx.db->query()) + { + if ( + function.filePath == file.filePath && + //check if function is in the current file + typeDefinitionPaths[function.returnType] != function.filePath && + //check for self relation + cc::util::isRootedUnderAnyOf(currentModulePaths,typeDefinitionPaths[function.returnType]) && + //check if return type is defined within the current module + relationsInCurrentFile.find(function.returnType) == relationsInCurrentFile.end() + //check if relation is already found + ) + { + ++relationsInModule; + relationsInCurrentFile.insert(function.returnType); + } + + } + + //check function parameters + for (const model::RelationalCohessionFunctionParameterView& parameter + : _ctx.db->query()) + { + if ( + parameter.filePath == file.filePath && + //check if the parameter is in the current file + typeDefinitionPaths[parameter.typeHash] != parameter.filePath && + //check for self relation + cc::util::isRootedUnderAnyOf(currentModulePaths,typeDefinitionPaths[parameter.typeHash]) && + //check if the type is defined within the current module + relationsInCurrentFile.find(parameter.typeHash) == relationsInCurrentFile.end() + //check if relation is already found + ) + { + ++relationsInModule; + relationsInCurrentFile.insert(parameter.typeHash); + } + + } + + //check function locals + for (const model::RelationalCohessionFunctionLocalView& local + : _ctx.db->query()) + { + if ( + local.filePath == file.filePath && + //check if the local variable is in the current file + typeDefinitionPaths[local.typeHash] != local.filePath && + //check for self relation + cc::util::isRootedUnderAnyOf(currentModulePaths,typeDefinitionPaths[local.typeHash]) && + //check if the type is defined within the current module + relationsInCurrentFile.find(local.typeHash) == relationsInCurrentFile.end() + //check if relation is already found + ) + { + ++relationsInModule; + relationsInCurrentFile.insert(local.typeHash); + } + + } + + //check variables + for (const model::RelationalCohesionVariableView& variable + : _ctx.db->query()) + { + if ( + variable.filePath == file.filePath && + //check if the variable is in the current file + typeDefinitionPaths[variable.typeHash] != variable.filePath && + //check for self relation + cc::util::isRootedUnderAnyOf(currentModulePaths,typeDefinitionPaths[variable.typeHash]) && + //check if the type is defined within the current module + relationsInCurrentFile.find(variable.typeHash) == relationsInCurrentFile.end() + //check if relation is already found + ) + { + ++relationsInModule; + relationsInCurrentFile.insert(variable.typeHash); + } + + } + + } + + } + //calculate relational cohesion for module + //formula: H = (R + 1)/ N + //where H is the relational cohesion value, + //R is the number of relationships internal to the module, + //N is the number of types in the module + + uint numberOfTypesInModule = typesUnderPath[path].size(); //N + + double relationalCohesion = + (static_cast(relationsInModule) + 1.0) / static_cast(numberOfTypesInModule); + + //TODO: persistance + + } + + + + + + }); +} + void CppMetricsParser::lackOfCohesion() { util::OdbTransaction {_ctx.db} ([&, this] From 313d540673b0a8b77b1ccf927b565cbb3e29f276 Mon Sep 17 00:00:00 2001 From: Klein Kristof Date: Wed, 8 May 2024 11:26:49 +0200 Subject: [PATCH 06/15] Fixed an include error --- .../model/include/model/cpprelationalcohesion.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h b/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h index 654cd3f7f..12da4424d 100644 --- a/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h +++ b/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h @@ -63,10 +63,12 @@ namespace cc std::string filePath; }; + // object(CppEntity) \ + #pragma db view \ - object(CppEntity) \ + object(CppFunction) \ object(CppVariable = Parameters : CppFunction::parameters) \ - object(CppAstNode : CppAstNode.id == CppEntity.astNodeId) \ + object(CppAstNode : CppAstNode::id == CppFunction::astNodeId) \ object(File : CppAstNode::location.file) struct RelationalCohessionFunctionParameterView { @@ -79,8 +81,9 @@ namespace cc #pragma db view \ + object(CppFunction) \ object(CppVariable = Locals : CppFunction::locals) \ - object(CppAstNode : CppAstNode.id == CppEntity.astNodeId) \ + object(CppAstNode : CppAstNode::id == CppFunction::astNodeId) \ object(File : CppAstNode::location.file) struct RelationalCohessionFunctionLocalView { @@ -93,7 +96,7 @@ namespace cc #pragma db view \ object(CppVariable) \ - object(CppAstNode : CppAstNode.id == CppEntity.astNodeId) \ + object(CppAstNode : CppAstNode::id == CppEntity::astNodeId) \ object(File : CppAstNode::location.file) struct RelationalCohesionVariableView { From 7ba19f9834fddd3473bcc9e77a3a6e96bf6759c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=BCkki=20D=C3=A1niel?= <64849783+dbukki@users.noreply.github.com> Date: Wed, 8 May 2024 15:17:16 +0200 Subject: [PATCH 07/15] Incremental parsing issue fixes (#736) Fix segmentation fault due to access of file ID on non-loaded file. Eliminated use of size() on ODB query result in SourceManager. Added isSingletonResult instead to dbutil. --- parser/src/sourcemanager.cpp | 5 +-- .../model/include/model/cppastnodemetrics.h | 13 +++++++ .../parser/src/cppmetricsparser.cpp | 8 ++--- util/include/util/dbutil.h | 34 +++++++++++++++++++ 4 files changed, 53 insertions(+), 7 deletions(-) diff --git a/parser/src/sourcemanager.cpp b/parser/src/sourcemanager.cpp index 114db9661..73868e859 100644 --- a/parser/src/sourcemanager.cpp +++ b/parser/src/sourcemanager.cpp @@ -5,6 +5,7 @@ #include #include +#include #include @@ -238,9 +239,9 @@ void SourceManager::removeFile(const model::File& file_) _transaction([&]() { if(file_.content) { - auto relFiles = _db->query( + odb::result relFiles = _db->query( odb::query::content == file_.content.object_id()); - if (relFiles.size() == 1) + if (util::isSingleResult(relFiles)) { removeContent = true; _db->erase(file_.content.object_id()); diff --git a/plugins/cpp_metrics/model/include/model/cppastnodemetrics.h b/plugins/cpp_metrics/model/include/model/cppastnodemetrics.h index 5c2f5b452..6b53bfd0b 100644 --- a/plugins/cpp_metrics/model/include/model/cppastnodemetrics.h +++ b/plugins/cpp_metrics/model/include/model/cppastnodemetrics.h @@ -45,6 +45,19 @@ struct CppRecordMetricsView double value; }; +#pragma db view \ + object(CppAstNodeMetrics) \ + object(CppAstNode : CppAstNodeMetrics::astNodeId == CppAstNode::id) \ + object(File : CppAstNode::location.file) +struct CppAstNodeMetricsFileView +{ + #pragma db column(CppAstNode::id) + CppAstNodeId astNodeId; + + #pragma db column(File::id) + FileId fileId; +}; + #pragma db view \ object(CppAstNodeMetrics) \ object(CppAstNode : CppAstNodeMetrics::astNodeId == CppAstNode::id) \ diff --git a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp index eace3bfc6..c7404d437 100644 --- a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp +++ b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp @@ -39,12 +39,10 @@ CppMetricsParser::CppMetricsParser(ParserContext& ctx_): AbstractParser(ctx_) _fileIdCache.insert(fm.file); } - for (const model::CppAstNodeMetrics& anm - : _ctx.db->query()) + for (const model::CppAstNodeMetricsFileView& anm + : _ctx.db->query()) { - auto node = _ctx.db->query_one( - odb::query::id == anm.astNodeId); - _astNodeIdCache.insert({anm.astNodeId, node->location.file->id}); + _astNodeIdCache.emplace(anm.astNodeId, anm.fileId); } }); } diff --git a/util/include/util/dbutil.h b/util/include/util/dbutil.h index 4a3d27514..5d1c331d5 100644 --- a/util/include/util/dbutil.h +++ b/util/include/util/dbutil.h @@ -97,6 +97,40 @@ inline std::string getDbDriver() #endif } +/// @brief Determines if the specified ODB query result only contains +/// a single entity. That single entity is then stored in 'single_'. +/// @tparam TEntity The type of entities in the query result. +/// @param result_ The ODB query result in question. +/// @param single_ The variable that receives the first entity (if any). +/// @return Returns true if 'result_' only contained 'single_'; +/// otherwise false. +template +bool isSingleResult(odb::result& result_, TEntity& single_) +{ + auto it_b = result_.begin(); + const auto it_e = result_.end(); + if (it_b != it_e) + { + single_ = *it_b; + return ++it_b == it_e; + } + else return false; +} + +/// @brief Determines if the specified ODB query result only contains +/// a single entity. +/// @tparam TEntity The type of entities in the query result. +/// @param result_ The ODB query result in question. +/// @return Returns true if 'result_' only contained a single entity; +/// otherwise false. +template +bool isSingleResult(odb::result& result_) +{ + auto it_b = result_.begin(); + const auto it_e = result_.end(); + return (it_b != it_e) && (++it_b == it_e); +} + } // util } // cc From 61a1f5fe2912f2abe1c177573b0e7c828b5577af Mon Sep 17 00:00:00 2001 From: Klein Kristof Date: Wed, 15 May 2024 11:06:49 +0200 Subject: [PATCH 08/15] Refactored relational cohesion calculation --- .../model/include/model/cppfilemetrics.h | 4 +- .../include/model/cpprelationalcohesion.h | 3 + .../parser/src/cppmetricsparser.cpp | 290 +++++++++--------- 3 files changed, 145 insertions(+), 152 deletions(-) diff --git a/plugins/cpp_metrics/model/include/model/cppfilemetrics.h b/plugins/cpp_metrics/model/include/model/cppfilemetrics.h index 357eb5cb5..ab462deba 100644 --- a/plugins/cpp_metrics/model/include/model/cppfilemetrics.h +++ b/plugins/cpp_metrics/model/include/model/cppfilemetrics.h @@ -13,7 +13,7 @@ struct CppFileMetrics { enum Type { - PLACEHOLDER + RELATIONAL_COHESION = 1 }; #pragma db id auto @@ -26,7 +26,7 @@ struct CppFileMetrics Type type; #pragma db not_null - unsigned value; + double value; }; } //model diff --git a/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h b/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h index 12da4424d..2e236badd 100644 --- a/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h +++ b/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h @@ -22,6 +22,9 @@ namespace cc #pragma db column(File::type) std::string fileType; + #pragma db column(File::id) + std::size_t fileId; + }; #pragma db view \ diff --git a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp index 3a71529c6..06a3bae0c 100644 --- a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp +++ b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp @@ -149,199 +149,188 @@ void CppMetricsParser::relationalCohesion() util::OdbTransaction {_ctx.db} ([&, this] { - std::unordered_set filepaths; - std::vector filepathVector; - filepathVector.insert(filepathVector.end(), filepaths.begin(), filepaths.end()); - std::unordered_map> pathsInModule; - std::unordered_map> typesUnderPath; - std::unordered_map> functionsUnderPath; + std::unordered_set filepaths(_inputPaths.begin(),_inputPaths.end()); std::unordered_map typeDefinitionPaths; + std::unordered_set typesFound; - //get the project filepaths - //change this later to only get the required modules - for (const model::RelationalCohesionFileView& file - : _ctx.db->query()) - { - if (cc::util::isRootedUnderAnyOf( _inputPaths, file.filePath) && - file.fileType == "DIR") - { - filepaths.insert(file.filePath); - } - } - //get what filepaths are contained within a module - for (auto &¤tPath : filepaths) + + //TODO: implement module handling logic + + std::unordered_map moduleIds; + + for (auto &&path : filepaths) { - std::vector pathVector; - pathVector.push_back(currentPath); - std::unordered_set pathsFound; - for (auto &&path : filepaths) + for(const model::RelationalCohesionFileView& file + : _ctx.db->query( + odb::query::query_columns::path.equal(path) + )) { - if (cc::util::isRootedUnderAnyOf(pathVector,path)) - { - pathsFound.insert(path); - } + moduleIds[path] = file.fileId; } - pathsInModule.insert(std::make_pair(currentPath,pathsFound)); } + - //find types defined under every filepath in the project - for (auto &¤tPath : filepaths) + for (auto &&path : filepaths) { - std::unordered_set typesFound; - std::vector pathVector; - pathVector.push_back(currentPath); + + typesFound.clear(); + typeDefinitionPaths.clear(); + //find the types defined in the module for (const model::RelationalCohesionRecordView& record - : _ctx.db->query()) + : _ctx.db->query( + odb::query::query_columns::File::path.like(path + "%") + )) + { + typesFound.insert(record.typeHash); //save types defined inside the module + typeDefinitionPaths.insert(std::make_pair(record.typeHash,record.filePath)); //save where the type is defined to avoid self relation + } + + std::unordered_map> relationsFoundInFile; //store the type relations already found for each file + int relationsInModule = 0; + + //check function return types + for (const model::RelationalCohesionFunctionView& function + : _ctx.db->query( + odb::query::query_columns::File::path.like(path + "%") + )) { - if (cc::util::isRootedUnderAnyOf(pathVector,record.filePath)) + if ( + typesFound.find(function.returnType) != typesFound.end() && + //check if return type is defined within the current module + typeDefinitionPaths[function.returnType] != function.filePath && + //check for self relation + (relationsFoundInFile.find(function.filePath) == relationsFoundInFile.end() || + //check if any reletaions were found in the current file + relationsFoundInFile[function.filePath].find(function.returnType) == relationsFoundInFile[function.filePath].end()) + //check if this relation is already found + ) { - typesFound.insert(record.typeHash); + ++relationsInModule; + auto it = relationsFoundInFile.find(function.filePath); + if (it != relationsFoundInFile.end()) + { + it->second.insert(function.returnType); + } + else + { + relationsFoundInFile.insert(std::make_pair(function.filePath,std::unordered_set{function.returnType})); + } } + } - typesUnderPath.insert(std::make_pair(currentPath,typesFound)); - } - //save where each type is defined so self relations can be excluded - for (const model::RelationalCohesionRecordView& record - : _ctx.db->query()) - { - typeDefinitionPaths.insert(std::make_pair(record.typeHash,record.filePath)); - } - - //find relations - for (auto &&path : filepaths) - { - std::vector currentModulePaths( - pathsInModule[path].begin(), pathsInModule[path].end() - ); - - uint relationsInModule = 0; //R - std::unordered_set relationsInCurrentFile; - std::unordered_set filesAlreadyChecked; - //select the next module - for (auto &&modulePath : currentModulePaths) + //check function parameters + for (const model::RelationalCohessionFunctionParameterView& parameter + : _ctx.db->query( + odb::query::query_columns::File::path.like(path + "%") + )) { - std::vector pathVector; - pathVector.push_back(modulePath); - //find the files defined under the current module member - for (const model::RelationalCohesionFileView& file - : _ctx.db->query()) + if ( + typesFound.find(parameter.typeHash) != typesFound.end() && + //check if return type is defined within the current module + typeDefinitionPaths[parameter.typeHash] != parameter.filePath && + //check for self relation + (relationsFoundInFile.find(parameter.filePath) == relationsFoundInFile.end() || + //check if any reletaions were found in the current file + relationsFoundInFile[parameter.filePath].find(parameter.typeHash) == relationsFoundInFile[parameter.filePath].end()) + //check if this relation is already found + ) { - if (file.fileType != "CPP" && - !cc::util::isRootedUnderAnyOf(pathVector,file.filePath) && - filesAlreadyChecked.find(file.filePath) != filesAlreadyChecked.end() - ) + ++relationsInModule; + auto it = relationsFoundInFile.find(parameter.filePath); + if (it != relationsFoundInFile.end()) { - continue; + it->second.insert(parameter.typeHash); } - filesAlreadyChecked.insert(file.filePath); - relationsInCurrentFile.clear(); - //check function return types - for (const model::RelationalCohesionFunctionView& function - : _ctx.db->query()) + else { - if ( - function.filePath == file.filePath && - //check if function is in the current file - typeDefinitionPaths[function.returnType] != function.filePath && - //check for self relation - cc::util::isRootedUnderAnyOf(currentModulePaths,typeDefinitionPaths[function.returnType]) && - //check if return type is defined within the current module - relationsInCurrentFile.find(function.returnType) == relationsInCurrentFile.end() - //check if relation is already found - ) - { - ++relationsInModule; - relationsInCurrentFile.insert(function.returnType); - } - + relationsFoundInFile.insert(std::make_pair(parameter.filePath,std::unordered_set{parameter.typeHash})); } + } + + } - //check function parameters - for (const model::RelationalCohessionFunctionParameterView& parameter - : _ctx.db->query()) + //check function locals + for (const model::RelationalCohessionFunctionLocalView& local + : _ctx.db->query( + odb::query::query_columns::File::path.like(path + "%") + )) + { + if ( + typesFound.find(local.typeHash) != typesFound.end() && + //check if return type is defined within the current module + typeDefinitionPaths[local.typeHash] != local.filePath && + //check for self relation + (relationsFoundInFile.find(local.filePath) == relationsFoundInFile.end() || + //check if any reletaions were found in the current file + relationsFoundInFile[local.filePath].find(local.typeHash) == relationsFoundInFile[local.filePath].end()) + //check if this relation is already found + ) + { + ++relationsInModule; + auto it = relationsFoundInFile.find(local.filePath); + if (it != relationsFoundInFile.end()) { - if ( - parameter.filePath == file.filePath && - //check if the parameter is in the current file - typeDefinitionPaths[parameter.typeHash] != parameter.filePath && - //check for self relation - cc::util::isRootedUnderAnyOf(currentModulePaths,typeDefinitionPaths[parameter.typeHash]) && - //check if the type is defined within the current module - relationsInCurrentFile.find(parameter.typeHash) == relationsInCurrentFile.end() - //check if relation is already found - ) - { - ++relationsInModule; - relationsInCurrentFile.insert(parameter.typeHash); - } - + it->second.insert(local.typeHash); } - - //check function locals - for (const model::RelationalCohessionFunctionLocalView& local - : _ctx.db->query()) + else { - if ( - local.filePath == file.filePath && - //check if the local variable is in the current file - typeDefinitionPaths[local.typeHash] != local.filePath && - //check for self relation - cc::util::isRootedUnderAnyOf(currentModulePaths,typeDefinitionPaths[local.typeHash]) && - //check if the type is defined within the current module - relationsInCurrentFile.find(local.typeHash) == relationsInCurrentFile.end() - //check if relation is already found - ) - { - ++relationsInModule; - relationsInCurrentFile.insert(local.typeHash); - } - + relationsFoundInFile.insert(std::make_pair(local.filePath,std::unordered_set{local.typeHash})); } + } + + } - //check variables - for (const model::RelationalCohesionVariableView& variable - : _ctx.db->query()) + //check variables + for (const model::RelationalCohesionVariableView& variable + : _ctx.db->query( + odb::query::query_columns::File::path.like(path + "%") + )) + { + if ( + typesFound.find(variable.typeHash) != typesFound.end() && + //check if return type is defined within the current module + typeDefinitionPaths[variable.typeHash] != variable.filePath && + //check for self relation + (relationsFoundInFile.find(variable.filePath) == relationsFoundInFile.end() || + //check if any reletaions were found in the current file + relationsFoundInFile[variable.filePath].find(variable.typeHash) == relationsFoundInFile[variable.filePath].end()) + //check if this relation is already found + ) + { + ++relationsInModule; + auto it = relationsFoundInFile.find(variable.filePath); + if (it != relationsFoundInFile.end()) { - if ( - variable.filePath == file.filePath && - //check if the variable is in the current file - typeDefinitionPaths[variable.typeHash] != variable.filePath && - //check for self relation - cc::util::isRootedUnderAnyOf(currentModulePaths,typeDefinitionPaths[variable.typeHash]) && - //check if the type is defined within the current module - relationsInCurrentFile.find(variable.typeHash) == relationsInCurrentFile.end() - //check if relation is already found - ) - { - ++relationsInModule; - relationsInCurrentFile.insert(variable.typeHash); - } - + it->second.insert(variable.typeHash); + } + else + { + relationsFoundInFile.insert(std::make_pair(variable.filePath,std::unordered_set{variable.typeHash})); } - } } + //calculate relational cohesion for module //formula: H = (R + 1)/ N //where H is the relational cohesion value, //R is the number of relationships internal to the module, //N is the number of types in the module - uint numberOfTypesInModule = typesUnderPath[path].size(); //N + uint numberOfTypesInModule = typesFound.size(); //N double relationalCohesion = (static_cast(relationsInModule) + 1.0) / static_cast(numberOfTypesInModule); - - //TODO: persistance - } - + model::CppFileMetrics relationalCohesionMetrics; + relationalCohesionMetrics.file = moduleIds[path]; + relationalCohesionMetrics.value = relationalCohesion; + relationalCohesionMetrics.type = model::CppFileMetrics::Type::RELATIONAL_COHESION; + _ctx.db->persist(relationalCohesionMetrics); - - + } }); } @@ -456,6 +445,7 @@ bool CppMetricsParser::parse() functionParameters(); functionMcCabe(); lackOfCohesion(); + relationalCohesion(); return true; } From bb94b8af69dd5db1a97c6d1ed97f97931d777277 Mon Sep 17 00:00:00 2001 From: Klein Kristof Date: Wed, 8 May 2024 09:59:50 +0200 Subject: [PATCH 09/15] Added calculation for relational cohesion --- plugins/cpp_metrics/model/CMakeLists.txt | 5 +- .../include/model/cpprelationalcohesion.h | 111 ++++++++++ .../cppmetricsparser/cppmetricsparser.h | 2 + .../parser/src/cppmetricsparser.cpp | 205 ++++++++++++++++++ 4 files changed, 321 insertions(+), 2 deletions(-) create mode 100644 plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h diff --git a/plugins/cpp_metrics/model/CMakeLists.txt b/plugins/cpp_metrics/model/CMakeLists.txt index 38d8ca343..580be0d66 100644 --- a/plugins/cpp_metrics/model/CMakeLists.txt +++ b/plugins/cpp_metrics/model/CMakeLists.txt @@ -5,11 +5,12 @@ include_directories( set(ODB_SOURCES include/model/cppastnodemetrics.h include/model/cppcohesionmetrics.h - include/model/cppfilemetrics.h) + include/model/cppfilemetrics.h + include/model/cpprelationalcohesion.h) generate_odb_files("${ODB_SOURCES}" "cpp") add_odb_library(cppmetricsmodel ${ODB_CXX_SOURCES}) target_link_libraries(cppmetricsmodel cppmodel) -install_sql() \ No newline at end of file +install_sql() diff --git a/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h b/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h new file mode 100644 index 000000000..654cd3f7f --- /dev/null +++ b/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h @@ -0,0 +1,111 @@ +#ifndef CC_MODEL_CPPRELATIONALCOHESION_H +#define CC_MODEL_CPPRELATIONALCOHESION_H + +#include +#include +#include +#include +#include + +namespace cc +{ + namespace model + { + + #pragma db view \ + object(File) + struct RelationalCohesionFileView + { + #pragma db column(File::path) + std::string filePath; + + #pragma db column(File::type) + std::string fileType; + + }; + + #pragma db view \ + object(CppRecord) \ + object(CppAstNode : CppRecord::astNodeId == CppAstNode::id) \ + object(File : CppAstNode::location.file) \ + object(CppMemberType : CppMemberType::memberAstNode) + struct RelationalCohesionRecordView + { + #pragma db column(CppEntity::entityHash) + std::size_t entityHash; + + #pragma db column(CppMemberType::typeHash) + std::size_t typeHash; + + #pragma db column(CppEntity::qualifiedName) + std::string qualifiedName; + + #pragma db column(CppEntity::astNodeId) + CppAstNodeId astNodeId; + + #pragma db column(File::path) + std::string filePath; + }; + + #pragma db view \ + object(CppFunction) \ + object(CppAstNode : CppFunction::astNodeId == CppAstNode::id) \ + object(File : CppAstNode::location.file) + struct RelationalCohesionFunctionView + { + #pragma db column(CppEntity::entityHash) + std::size_t entityHash; + + #pragma db column(CppTypedEntity::typeHash) + std::size_t returnType; + + #pragma db column(File::path) + std::string filePath; + }; + + #pragma db view \ + object(CppEntity) \ + object(CppVariable = Parameters : CppFunction::parameters) \ + object(CppAstNode : CppAstNode.id == CppEntity.astNodeId) \ + object(File : CppAstNode::location.file) + struct RelationalCohessionFunctionParameterView + { + #pragma db column(Parameters::typeHash) + std::size_t typeHash; + + #pragma db column(File::path) + std::string filePath; + }; + + + #pragma db view \ + object(CppVariable = Locals : CppFunction::locals) \ + object(CppAstNode : CppAstNode.id == CppEntity.astNodeId) \ + object(File : CppAstNode::location.file) + struct RelationalCohessionFunctionLocalView + { + #pragma db column(Locals::typeHash) + std::size_t typeHash; + + #pragma db column(File::path) + std::string filePath; + }; + + #pragma db view \ + object(CppVariable) \ + object(CppAstNode : CppAstNode.id == CppEntity.astNodeId) \ + object(File : CppAstNode::location.file) + struct RelationalCohesionVariableView + { + #pragma db column(CppVariable::typeHash) + std::size_t typeHash; + + #pragma db column(File::path) + std::string filePath; + + }; + + } +} + +#endif \ No newline at end of file diff --git a/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h b/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h index 5abe1af83..f888a771b 100644 --- a/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h +++ b/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h @@ -40,6 +40,8 @@ class CppMetricsParser : public AbstractParser // Calculate the lack of cohesion between member variables // and member functions for every type. void lackOfCohesion(); + // Calculate the cohesion within modules + void relationalCohesion(); std::vector _inputPaths; std::unordered_set _fileIdCache; diff --git a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp index c7404d437..c89c12c10 100644 --- a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp +++ b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include @@ -18,6 +20,7 @@ #include #include +#include namespace cc { @@ -163,6 +166,208 @@ void CppMetricsParser::functionBumpyRoad() }); } +void CppMetricsParser::relationalCohesion() +{ + util::OdbTransaction {_ctx.db} ([&, this] + { + + std::unordered_set filepaths; + std::vector filepathVector; + filepathVector.insert(filepathVector.end(), filepaths.begin(), filepaths.end()); + std::unordered_map> pathsInModule; + std::unordered_map> typesUnderPath; + std::unordered_map> functionsUnderPath; + std::unordered_map typeDefinitionPaths; + + //get the project filepaths + //change this later to only get the required modules + for (const model::RelationalCohesionFileView& file + : _ctx.db->query()) + { + if (cc::util::isRootedUnderAnyOf( _inputPaths, file.filePath) && + file.fileType == "DIR") + { + filepaths.insert(file.filePath); + } + } + + //get what filepaths are contained within a module + for (auto &¤tPath : filepaths) + { + std::vector pathVector; + pathVector.push_back(currentPath); + std::unordered_set pathsFound; + for (auto &&path : filepaths) + { + if (cc::util::isRootedUnderAnyOf(pathVector,path)) + { + pathsFound.insert(path); + } + } + pathsInModule.insert(std::make_pair(currentPath,pathsFound)); + } + + //find types defined under every filepath in the project + for (auto &¤tPath : filepaths) + { + std::unordered_set typesFound; + std::vector pathVector; + pathVector.push_back(currentPath); + for (const model::RelationalCohesionRecordView& record + : _ctx.db->query()) + { + if (cc::util::isRootedUnderAnyOf(pathVector,record.filePath)) + { + typesFound.insert(record.typeHash); + } + } + typesUnderPath.insert(std::make_pair(currentPath,typesFound)); + } + + //save where each type is defined so self relations can be excluded + for (const model::RelationalCohesionRecordView& record + : _ctx.db->query()) + { + typeDefinitionPaths.insert(std::make_pair(record.typeHash,record.filePath)); + } + + //find relations + for (auto &&path : filepaths) + { + std::vector currentModulePaths( + pathsInModule[path].begin(), pathsInModule[path].end() + ); + + uint relationsInModule = 0; //R + std::unordered_set relationsInCurrentFile; + std::unordered_set filesAlreadyChecked; + //select the next module + for (auto &&modulePath : currentModulePaths) + { + std::vector pathVector; + pathVector.push_back(modulePath); + //find the files defined under the current module member + for (const model::RelationalCohesionFileView& file + : _ctx.db->query()) + { + if (file.fileType != "CPP" && + !cc::util::isRootedUnderAnyOf(pathVector,file.filePath) && + filesAlreadyChecked.find(file.filePath) != filesAlreadyChecked.end() + ) + { + continue; + } + filesAlreadyChecked.insert(file.filePath); + relationsInCurrentFile.clear(); + //check function return types + for (const model::RelationalCohesionFunctionView& function + : _ctx.db->query()) + { + if ( + function.filePath == file.filePath && + //check if function is in the current file + typeDefinitionPaths[function.returnType] != function.filePath && + //check for self relation + cc::util::isRootedUnderAnyOf(currentModulePaths,typeDefinitionPaths[function.returnType]) && + //check if return type is defined within the current module + relationsInCurrentFile.find(function.returnType) == relationsInCurrentFile.end() + //check if relation is already found + ) + { + ++relationsInModule; + relationsInCurrentFile.insert(function.returnType); + } + + } + + //check function parameters + for (const model::RelationalCohessionFunctionParameterView& parameter + : _ctx.db->query()) + { + if ( + parameter.filePath == file.filePath && + //check if the parameter is in the current file + typeDefinitionPaths[parameter.typeHash] != parameter.filePath && + //check for self relation + cc::util::isRootedUnderAnyOf(currentModulePaths,typeDefinitionPaths[parameter.typeHash]) && + //check if the type is defined within the current module + relationsInCurrentFile.find(parameter.typeHash) == relationsInCurrentFile.end() + //check if relation is already found + ) + { + ++relationsInModule; + relationsInCurrentFile.insert(parameter.typeHash); + } + + } + + //check function locals + for (const model::RelationalCohessionFunctionLocalView& local + : _ctx.db->query()) + { + if ( + local.filePath == file.filePath && + //check if the local variable is in the current file + typeDefinitionPaths[local.typeHash] != local.filePath && + //check for self relation + cc::util::isRootedUnderAnyOf(currentModulePaths,typeDefinitionPaths[local.typeHash]) && + //check if the type is defined within the current module + relationsInCurrentFile.find(local.typeHash) == relationsInCurrentFile.end() + //check if relation is already found + ) + { + ++relationsInModule; + relationsInCurrentFile.insert(local.typeHash); + } + + } + + //check variables + for (const model::RelationalCohesionVariableView& variable + : _ctx.db->query()) + { + if ( + variable.filePath == file.filePath && + //check if the variable is in the current file + typeDefinitionPaths[variable.typeHash] != variable.filePath && + //check for self relation + cc::util::isRootedUnderAnyOf(currentModulePaths,typeDefinitionPaths[variable.typeHash]) && + //check if the type is defined within the current module + relationsInCurrentFile.find(variable.typeHash) == relationsInCurrentFile.end() + //check if relation is already found + ) + { + ++relationsInModule; + relationsInCurrentFile.insert(variable.typeHash); + } + + } + + } + + } + //calculate relational cohesion for module + //formula: H = (R + 1)/ N + //where H is the relational cohesion value, + //R is the number of relationships internal to the module, + //N is the number of types in the module + + uint numberOfTypesInModule = typesUnderPath[path].size(); //N + + double relationalCohesion = + (static_cast(relationsInModule) + 1.0) / static_cast(numberOfTypesInModule); + + //TODO: persistance + + } + + + + + + }); +} + void CppMetricsParser::lackOfCohesion() { util::OdbTransaction {_ctx.db} ([&, this] From 310da0b06662576b0e89be3279a8fa99a7a68d94 Mon Sep 17 00:00:00 2001 From: Klein Kristof Date: Wed, 8 May 2024 11:26:49 +0200 Subject: [PATCH 10/15] Fixed an include error --- .../model/include/model/cpprelationalcohesion.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h b/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h index 654cd3f7f..12da4424d 100644 --- a/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h +++ b/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h @@ -63,10 +63,12 @@ namespace cc std::string filePath; }; + // object(CppEntity) \ + #pragma db view \ - object(CppEntity) \ + object(CppFunction) \ object(CppVariable = Parameters : CppFunction::parameters) \ - object(CppAstNode : CppAstNode.id == CppEntity.astNodeId) \ + object(CppAstNode : CppAstNode::id == CppFunction::astNodeId) \ object(File : CppAstNode::location.file) struct RelationalCohessionFunctionParameterView { @@ -79,8 +81,9 @@ namespace cc #pragma db view \ + object(CppFunction) \ object(CppVariable = Locals : CppFunction::locals) \ - object(CppAstNode : CppAstNode.id == CppEntity.astNodeId) \ + object(CppAstNode : CppAstNode::id == CppFunction::astNodeId) \ object(File : CppAstNode::location.file) struct RelationalCohessionFunctionLocalView { @@ -93,7 +96,7 @@ namespace cc #pragma db view \ object(CppVariable) \ - object(CppAstNode : CppAstNode.id == CppEntity.astNodeId) \ + object(CppAstNode : CppAstNode::id == CppEntity::astNodeId) \ object(File : CppAstNode::location.file) struct RelationalCohesionVariableView { From 5b519590a8c6f96aac581b3bd349bec05baef4a3 Mon Sep 17 00:00:00 2001 From: Klein Kristof Date: Wed, 15 May 2024 11:06:49 +0200 Subject: [PATCH 11/15] Refactored relational cohesion calculation --- .../model/include/model/cppfilemetrics.h | 4 +- .../include/model/cpprelationalcohesion.h | 3 + .../parser/src/cppmetricsparser.cpp | 290 +++++++++--------- 3 files changed, 145 insertions(+), 152 deletions(-) diff --git a/plugins/cpp_metrics/model/include/model/cppfilemetrics.h b/plugins/cpp_metrics/model/include/model/cppfilemetrics.h index eebedbc46..95c393e1a 100644 --- a/plugins/cpp_metrics/model/include/model/cppfilemetrics.h +++ b/plugins/cpp_metrics/model/include/model/cppfilemetrics.h @@ -13,7 +13,7 @@ struct CppFileMetrics { enum Type { - PLACEHOLDER + RELATIONAL_COHESION = 1 }; #pragma db id auto @@ -26,7 +26,7 @@ struct CppFileMetrics Type type; #pragma db not_null - unsigned value; + double value; }; #pragma db view \ diff --git a/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h b/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h index 12da4424d..2e236badd 100644 --- a/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h +++ b/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h @@ -22,6 +22,9 @@ namespace cc #pragma db column(File::type) std::string fileType; + #pragma db column(File::id) + std::size_t fileId; + }; #pragma db view \ diff --git a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp index c89c12c10..b778f0900 100644 --- a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp +++ b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp @@ -171,199 +171,188 @@ void CppMetricsParser::relationalCohesion() util::OdbTransaction {_ctx.db} ([&, this] { - std::unordered_set filepaths; - std::vector filepathVector; - filepathVector.insert(filepathVector.end(), filepaths.begin(), filepaths.end()); - std::unordered_map> pathsInModule; - std::unordered_map> typesUnderPath; - std::unordered_map> functionsUnderPath; + std::unordered_set filepaths(_inputPaths.begin(),_inputPaths.end()); std::unordered_map typeDefinitionPaths; + std::unordered_set typesFound; - //get the project filepaths - //change this later to only get the required modules - for (const model::RelationalCohesionFileView& file - : _ctx.db->query()) - { - if (cc::util::isRootedUnderAnyOf( _inputPaths, file.filePath) && - file.fileType == "DIR") - { - filepaths.insert(file.filePath); - } - } - //get what filepaths are contained within a module - for (auto &¤tPath : filepaths) + + //TODO: implement module handling logic + + std::unordered_map moduleIds; + + for (auto &&path : filepaths) { - std::vector pathVector; - pathVector.push_back(currentPath); - std::unordered_set pathsFound; - for (auto &&path : filepaths) + for(const model::RelationalCohesionFileView& file + : _ctx.db->query( + odb::query::query_columns::path.equal(path) + )) { - if (cc::util::isRootedUnderAnyOf(pathVector,path)) - { - pathsFound.insert(path); - } + moduleIds[path] = file.fileId; } - pathsInModule.insert(std::make_pair(currentPath,pathsFound)); } + - //find types defined under every filepath in the project - for (auto &¤tPath : filepaths) + for (auto &&path : filepaths) { - std::unordered_set typesFound; - std::vector pathVector; - pathVector.push_back(currentPath); + + typesFound.clear(); + typeDefinitionPaths.clear(); + //find the types defined in the module for (const model::RelationalCohesionRecordView& record - : _ctx.db->query()) + : _ctx.db->query( + odb::query::query_columns::File::path.like(path + "%") + )) + { + typesFound.insert(record.typeHash); //save types defined inside the module + typeDefinitionPaths.insert(std::make_pair(record.typeHash,record.filePath)); //save where the type is defined to avoid self relation + } + + std::unordered_map> relationsFoundInFile; //store the type relations already found for each file + int relationsInModule = 0; + + //check function return types + for (const model::RelationalCohesionFunctionView& function + : _ctx.db->query( + odb::query::query_columns::File::path.like(path + "%") + )) { - if (cc::util::isRootedUnderAnyOf(pathVector,record.filePath)) + if ( + typesFound.find(function.returnType) != typesFound.end() && + //check if return type is defined within the current module + typeDefinitionPaths[function.returnType] != function.filePath && + //check for self relation + (relationsFoundInFile.find(function.filePath) == relationsFoundInFile.end() || + //check if any reletaions were found in the current file + relationsFoundInFile[function.filePath].find(function.returnType) == relationsFoundInFile[function.filePath].end()) + //check if this relation is already found + ) { - typesFound.insert(record.typeHash); + ++relationsInModule; + auto it = relationsFoundInFile.find(function.filePath); + if (it != relationsFoundInFile.end()) + { + it->second.insert(function.returnType); + } + else + { + relationsFoundInFile.insert(std::make_pair(function.filePath,std::unordered_set{function.returnType})); + } } + } - typesUnderPath.insert(std::make_pair(currentPath,typesFound)); - } - //save where each type is defined so self relations can be excluded - for (const model::RelationalCohesionRecordView& record - : _ctx.db->query()) - { - typeDefinitionPaths.insert(std::make_pair(record.typeHash,record.filePath)); - } - - //find relations - for (auto &&path : filepaths) - { - std::vector currentModulePaths( - pathsInModule[path].begin(), pathsInModule[path].end() - ); - - uint relationsInModule = 0; //R - std::unordered_set relationsInCurrentFile; - std::unordered_set filesAlreadyChecked; - //select the next module - for (auto &&modulePath : currentModulePaths) + //check function parameters + for (const model::RelationalCohessionFunctionParameterView& parameter + : _ctx.db->query( + odb::query::query_columns::File::path.like(path + "%") + )) { - std::vector pathVector; - pathVector.push_back(modulePath); - //find the files defined under the current module member - for (const model::RelationalCohesionFileView& file - : _ctx.db->query()) + if ( + typesFound.find(parameter.typeHash) != typesFound.end() && + //check if return type is defined within the current module + typeDefinitionPaths[parameter.typeHash] != parameter.filePath && + //check for self relation + (relationsFoundInFile.find(parameter.filePath) == relationsFoundInFile.end() || + //check if any reletaions were found in the current file + relationsFoundInFile[parameter.filePath].find(parameter.typeHash) == relationsFoundInFile[parameter.filePath].end()) + //check if this relation is already found + ) { - if (file.fileType != "CPP" && - !cc::util::isRootedUnderAnyOf(pathVector,file.filePath) && - filesAlreadyChecked.find(file.filePath) != filesAlreadyChecked.end() - ) + ++relationsInModule; + auto it = relationsFoundInFile.find(parameter.filePath); + if (it != relationsFoundInFile.end()) { - continue; + it->second.insert(parameter.typeHash); } - filesAlreadyChecked.insert(file.filePath); - relationsInCurrentFile.clear(); - //check function return types - for (const model::RelationalCohesionFunctionView& function - : _ctx.db->query()) + else { - if ( - function.filePath == file.filePath && - //check if function is in the current file - typeDefinitionPaths[function.returnType] != function.filePath && - //check for self relation - cc::util::isRootedUnderAnyOf(currentModulePaths,typeDefinitionPaths[function.returnType]) && - //check if return type is defined within the current module - relationsInCurrentFile.find(function.returnType) == relationsInCurrentFile.end() - //check if relation is already found - ) - { - ++relationsInModule; - relationsInCurrentFile.insert(function.returnType); - } - + relationsFoundInFile.insert(std::make_pair(parameter.filePath,std::unordered_set{parameter.typeHash})); } + } + + } - //check function parameters - for (const model::RelationalCohessionFunctionParameterView& parameter - : _ctx.db->query()) + //check function locals + for (const model::RelationalCohessionFunctionLocalView& local + : _ctx.db->query( + odb::query::query_columns::File::path.like(path + "%") + )) + { + if ( + typesFound.find(local.typeHash) != typesFound.end() && + //check if return type is defined within the current module + typeDefinitionPaths[local.typeHash] != local.filePath && + //check for self relation + (relationsFoundInFile.find(local.filePath) == relationsFoundInFile.end() || + //check if any reletaions were found in the current file + relationsFoundInFile[local.filePath].find(local.typeHash) == relationsFoundInFile[local.filePath].end()) + //check if this relation is already found + ) + { + ++relationsInModule; + auto it = relationsFoundInFile.find(local.filePath); + if (it != relationsFoundInFile.end()) { - if ( - parameter.filePath == file.filePath && - //check if the parameter is in the current file - typeDefinitionPaths[parameter.typeHash] != parameter.filePath && - //check for self relation - cc::util::isRootedUnderAnyOf(currentModulePaths,typeDefinitionPaths[parameter.typeHash]) && - //check if the type is defined within the current module - relationsInCurrentFile.find(parameter.typeHash) == relationsInCurrentFile.end() - //check if relation is already found - ) - { - ++relationsInModule; - relationsInCurrentFile.insert(parameter.typeHash); - } - + it->second.insert(local.typeHash); } - - //check function locals - for (const model::RelationalCohessionFunctionLocalView& local - : _ctx.db->query()) + else { - if ( - local.filePath == file.filePath && - //check if the local variable is in the current file - typeDefinitionPaths[local.typeHash] != local.filePath && - //check for self relation - cc::util::isRootedUnderAnyOf(currentModulePaths,typeDefinitionPaths[local.typeHash]) && - //check if the type is defined within the current module - relationsInCurrentFile.find(local.typeHash) == relationsInCurrentFile.end() - //check if relation is already found - ) - { - ++relationsInModule; - relationsInCurrentFile.insert(local.typeHash); - } - + relationsFoundInFile.insert(std::make_pair(local.filePath,std::unordered_set{local.typeHash})); } + } + + } - //check variables - for (const model::RelationalCohesionVariableView& variable - : _ctx.db->query()) + //check variables + for (const model::RelationalCohesionVariableView& variable + : _ctx.db->query( + odb::query::query_columns::File::path.like(path + "%") + )) + { + if ( + typesFound.find(variable.typeHash) != typesFound.end() && + //check if return type is defined within the current module + typeDefinitionPaths[variable.typeHash] != variable.filePath && + //check for self relation + (relationsFoundInFile.find(variable.filePath) == relationsFoundInFile.end() || + //check if any reletaions were found in the current file + relationsFoundInFile[variable.filePath].find(variable.typeHash) == relationsFoundInFile[variable.filePath].end()) + //check if this relation is already found + ) + { + ++relationsInModule; + auto it = relationsFoundInFile.find(variable.filePath); + if (it != relationsFoundInFile.end()) { - if ( - variable.filePath == file.filePath && - //check if the variable is in the current file - typeDefinitionPaths[variable.typeHash] != variable.filePath && - //check for self relation - cc::util::isRootedUnderAnyOf(currentModulePaths,typeDefinitionPaths[variable.typeHash]) && - //check if the type is defined within the current module - relationsInCurrentFile.find(variable.typeHash) == relationsInCurrentFile.end() - //check if relation is already found - ) - { - ++relationsInModule; - relationsInCurrentFile.insert(variable.typeHash); - } - + it->second.insert(variable.typeHash); + } + else + { + relationsFoundInFile.insert(std::make_pair(variable.filePath,std::unordered_set{variable.typeHash})); } - } } + //calculate relational cohesion for module //formula: H = (R + 1)/ N //where H is the relational cohesion value, //R is the number of relationships internal to the module, //N is the number of types in the module - uint numberOfTypesInModule = typesUnderPath[path].size(); //N + uint numberOfTypesInModule = typesFound.size(); //N double relationalCohesion = (static_cast(relationsInModule) + 1.0) / static_cast(numberOfTypesInModule); - - //TODO: persistance - } - + model::CppFileMetrics relationalCohesionMetrics; + relationalCohesionMetrics.file = moduleIds[path]; + relationalCohesionMetrics.value = relationalCohesion; + relationalCohesionMetrics.type = model::CppFileMetrics::Type::RELATIONAL_COHESION; + _ctx.db->persist(relationalCohesionMetrics); - - + } }); } @@ -483,6 +472,7 @@ bool CppMetricsParser::parse() functionBumpyRoad(); LOG(info) << "[cppmetricsparser] Computing Lack of Cohesion metric for types."; lackOfCohesion(); + relationalCohesion(); return true; } From 212e18de082f0bc0512e32b487f1a1361fcf199c Mon Sep 17 00:00:00 2001 From: Klein Kristof Date: Fri, 21 Jun 2024 21:16:30 +0200 Subject: [PATCH 12/15] Moved type calculation into its own method --- .../include/model/cpprelationalcohesion.h | 2 +- .../cppmetricsparser/cppmetricsparser.h | 11 + .../parser/src/cppmetricsparser.cpp | 253 ++++++++---------- 3 files changed, 128 insertions(+), 138 deletions(-) diff --git a/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h b/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h index 2e236badd..cfe4c4c30 100644 --- a/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h +++ b/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h @@ -60,7 +60,7 @@ namespace cc std::size_t entityHash; #pragma db column(CppTypedEntity::typeHash) - std::size_t returnType; + std::size_t typeHash; #pragma db column(File::path) std::string filePath; diff --git a/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h b/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h index f888a771b..4c6b75e9a 100644 --- a/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h +++ b/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h @@ -42,8 +42,19 @@ class CppMetricsParser : public AbstractParser void lackOfCohesion(); // Calculate the cohesion within modules void relationalCohesion(); + // Check type relations in template parameter view. + // Used in relational cohesion metric. + template + void checkTypes( + const std::string path, + const std::unordered_set& typesFound, + const std::unordered_map& typeDefinitionPaths, + std::unordered_map>& relationsFoundInFile, + int& relationsInModule + ); std::vector _inputPaths; + std::string _modulesPath; std::unordered_set _fileIdCache; std::unordered_map _astNodeIdCache; std::unique_ptr> _pool; diff --git a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp index 321e9be19..f87e54713 100644 --- a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp +++ b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp @@ -35,6 +35,8 @@ CppMetricsParser::CppMetricsParser(ParserContext& ctx_): AbstractParser(ctx_) _ctx.options["input"].as>()) _inputPaths.push_back(fs::canonical(path).string()); + _modulesPath = _ctx.options["modules"].as(); + util::OdbTransaction {_ctx.db} ([&, this] { for (const model::CppFileMetrics& fm : _ctx.db->query()) @@ -142,7 +144,6 @@ void CppMetricsParser::functionMcCabe() }); } -<<<<<<< HEAD void CppMetricsParser::functionBumpyRoad() { util::OdbTransaction {_ctx.db} ([&, this] @@ -167,36 +168,95 @@ void CppMetricsParser::functionBumpyRoad() }); } -======= ->>>>>>> 61a1f5fe2912f2abe1c177573b0e7c828b5577af +template +void CppMetricsParser::checkTypes( + const std::string path, + const std::unordered_set& typesFound, + const std::unordered_map& typeDefinitionPaths, + std::unordered_map>& relationsFoundInFile, + int& relationsInModule +) +{ + for (const T& item + : _ctx.db->query( + odb::query::query_columns::File::path.like(path + "%") + )) + { + if ( + typesFound.find(item.typeHash) != typesFound.end() && + //check if return type is defined within the current module + typeDefinitionPaths.at(item.typeHash) != item.filePath && + //check for self relation + (relationsFoundInFile.find(item.filePath) == relationsFoundInFile.end() || + //check if any reletaions were found in the current file + relationsFoundInFile[item.filePath].find(item.typeHash) == relationsFoundInFile[item.filePath].end()) + //check if this relation is already found + ) + { + ++relationsInModule; + auto it = relationsFoundInFile.find(item.filePath); + if (it != relationsFoundInFile.end()) + { + it->second.insert(item.typeHash); + } + else + { + relationsFoundInFile.insert(std::make_pair(item.filePath,std::unordered_set{item.typeHash})); + } + } + } +} + void CppMetricsParser::relationalCohesion() { + std::unordered_set filepaths; + std::unordered_map typeDefinitionPaths; + std::unordered_set typesFound; + std::unordered_map moduleIds; + util::OdbTransaction {_ctx.db} ([&, this] { - std::unordered_set filepaths(_inputPaths.begin(),_inputPaths.end()); - std::unordered_map typeDefinitionPaths; - std::unordered_set typesFound; - + std::ifstream file(_modulesPath); - - //TODO: implement module handling logic - - std::unordered_map moduleIds; - - for (auto &&path : filepaths) + //read the specified module list if given + if (file.is_open()) { - for(const model::RelationalCohesionFileView& file - : _ctx.db->query( - odb::query::query_columns::path.equal(path) - )) + std::string line; + while (std::getline(file,line)) { - moduleIds[path] = file.fileId; + filepaths.insert(line); } } - + //if no modules list is specified every directory under the input paths is considered one + else + { + for (const auto &inputPath : _inputPaths) + { + for (const model::RelationalCohesionFileView& file + : _ctx.db->query( + odb::query::query_columns::path.like(inputPath + "%") && + odb::query::query_columns::type.equal("DIR") + )) + { + filepaths.insert(file.filePath); + } + } + } + + //get the file IDs for each module + for (auto &path : filepaths) + { + for (const model::RelationalCohesionFileView& file + : _ctx.db->query( + odb::query::query_columns::path.like(path) + )) + { + moduleIds[file.filePath] = file.fileId; + } + } - for (auto &&path : filepaths) + for (const auto &path : filepaths) { typesFound.clear(); @@ -215,129 +275,41 @@ void CppMetricsParser::relationalCohesion() int relationsInModule = 0; //check function return types - for (const model::RelationalCohesionFunctionView& function - : _ctx.db->query( - odb::query::query_columns::File::path.like(path + "%") - )) - { - if ( - typesFound.find(function.returnType) != typesFound.end() && - //check if return type is defined within the current module - typeDefinitionPaths[function.returnType] != function.filePath && - //check for self relation - (relationsFoundInFile.find(function.filePath) == relationsFoundInFile.end() || - //check if any reletaions were found in the current file - relationsFoundInFile[function.filePath].find(function.returnType) == relationsFoundInFile[function.filePath].end()) - //check if this relation is already found - ) - { - ++relationsInModule; - auto it = relationsFoundInFile.find(function.filePath); - if (it != relationsFoundInFile.end()) - { - it->second.insert(function.returnType); - } - else - { - relationsFoundInFile.insert(std::make_pair(function.filePath,std::unordered_set{function.returnType})); - } - } - - } + CppMetricsParser::checkTypes( + path, + typesFound, + typeDefinitionPaths, + relationsFoundInFile, + relationsInModule + ); //check function parameters - for (const model::RelationalCohessionFunctionParameterView& parameter - : _ctx.db->query( - odb::query::query_columns::File::path.like(path + "%") - )) - { - if ( - typesFound.find(parameter.typeHash) != typesFound.end() && - //check if return type is defined within the current module - typeDefinitionPaths[parameter.typeHash] != parameter.filePath && - //check for self relation - (relationsFoundInFile.find(parameter.filePath) == relationsFoundInFile.end() || - //check if any reletaions were found in the current file - relationsFoundInFile[parameter.filePath].find(parameter.typeHash) == relationsFoundInFile[parameter.filePath].end()) - //check if this relation is already found - ) - { - ++relationsInModule; - auto it = relationsFoundInFile.find(parameter.filePath); - if (it != relationsFoundInFile.end()) - { - it->second.insert(parameter.typeHash); - } - else - { - relationsFoundInFile.insert(std::make_pair(parameter.filePath,std::unordered_set{parameter.typeHash})); - } - } - - } + CppMetricsParser::checkTypes( + path, + typesFound, + typeDefinitionPaths, + relationsFoundInFile, + relationsInModule + ); //check function locals - for (const model::RelationalCohessionFunctionLocalView& local - : _ctx.db->query( - odb::query::query_columns::File::path.like(path + "%") - )) - { - if ( - typesFound.find(local.typeHash) != typesFound.end() && - //check if return type is defined within the current module - typeDefinitionPaths[local.typeHash] != local.filePath && - //check for self relation - (relationsFoundInFile.find(local.filePath) == relationsFoundInFile.end() || - //check if any reletaions were found in the current file - relationsFoundInFile[local.filePath].find(local.typeHash) == relationsFoundInFile[local.filePath].end()) - //check if this relation is already found - ) - { - ++relationsInModule; - auto it = relationsFoundInFile.find(local.filePath); - if (it != relationsFoundInFile.end()) - { - it->second.insert(local.typeHash); - } - else - { - relationsFoundInFile.insert(std::make_pair(local.filePath,std::unordered_set{local.typeHash})); - } - } - - } + CppMetricsParser::checkTypes( + path, + typesFound, + typeDefinitionPaths, + relationsFoundInFile, + relationsInModule + ); //check variables - for (const model::RelationalCohesionVariableView& variable - : _ctx.db->query( - odb::query::query_columns::File::path.like(path + "%") - )) - { - if ( - typesFound.find(variable.typeHash) != typesFound.end() && - //check if return type is defined within the current module - typeDefinitionPaths[variable.typeHash] != variable.filePath && - //check for self relation - (relationsFoundInFile.find(variable.filePath) == relationsFoundInFile.end() || - //check if any reletaions were found in the current file - relationsFoundInFile[variable.filePath].find(variable.typeHash) == relationsFoundInFile[variable.filePath].end()) - //check if this relation is already found - ) - { - ++relationsInModule; - auto it = relationsFoundInFile.find(variable.filePath); - if (it != relationsFoundInFile.end()) - { - it->second.insert(variable.typeHash); - } - else - { - relationsFoundInFile.insert(std::make_pair(variable.filePath,std::unordered_set{variable.typeHash})); - } - } - - } - + CppMetricsParser::checkTypes( + path, + typesFound, + typeDefinitionPaths, + relationsFoundInFile, + relationsInModule + ); + //calculate relational cohesion for module //formula: H = (R + 1)/ N //where H is the relational cohesion value, @@ -475,6 +447,7 @@ bool CppMetricsParser::parse() functionBumpyRoad(); LOG(info) << "[cppmetricsparser] Computing Lack of Cohesion metric for types."; lackOfCohesion(); + LOG(info) << "[cppmetricsparser] Computing Relational Cohesion metric for modules."; relationalCohesion(); return true; } @@ -501,7 +474,13 @@ extern "C" { boost::program_options::options_description description("C++ Metrics Plugin"); + description.add_options() + ("modules,m", po::value()->default_value("Unspecified"), + "The user specifies the path to the modules list here."); + return description; + + } std::shared_ptr make(ParserContext& ctx_) From cfc9ad29d11635fb0b2a451d14be04b223bd8400 Mon Sep 17 00:00:00 2001 From: Klein Kristof Date: Sat, 6 Jul 2024 19:39:22 +0200 Subject: [PATCH 13/15] Fixed requested changes --- .../include/model/cpprelationalcohesion.h | 1 - .../cppmetricsparser/cppmetricsparser.h | 4 +- .../parser/src/cppmetricsparser.cpp | 147 +++++++++--------- .../test/sources/parser/CMakeLists.txt | 7 +- .../MultipleTypesInModuleNoRelation/A.cpp | 1 + .../MultipleTypesInModuleNoRelation/B.cpp | 1 + .../MultipleTypesInModuleNoRelation/C.cpp | 1 + .../MultipleTypesInModuleNoRelation/D.cpp | 1 + .../RelationByFunctionParameter/A.cpp | 3 + .../RelationByFunctionParameter/A.h | 13 ++ .../RelationByFunctionParameter/B.cpp | 3 + .../RelationByFunctionParameter/B.h | 14 ++ .../RelationByFunctionParameter/C.cpp | 3 + .../RelationByFunctionParameter/C.h | 13 ++ .../RelationByFunctionParameter/D.cpp | 1 + .../RelationByFunctionParameter/D.h | 6 + .../OneTypeInModule/singleTypeInModule.cpp | 1 + .../test/src/cppmetricsparsertest.cpp | 44 ++++++ 18 files changed, 184 insertions(+), 80 deletions(-) create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/A.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/B.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/C.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/D.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/A.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/A.h create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/B.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/B.h create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/C.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/C.h create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/D.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/D.h create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/OneTypeInModule/singleTypeInModule.cpp diff --git a/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h b/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h index cfe4c4c30..216afb91a 100644 --- a/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h +++ b/plugins/cpp_metrics/model/include/model/cpprelationalcohesion.h @@ -66,7 +66,6 @@ namespace cc std::string filePath; }; - // object(CppEntity) \ #pragma db view \ object(CppFunction) \ diff --git a/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h b/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h index 4c6b75e9a..798d2e362 100644 --- a/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h +++ b/plugins/cpp_metrics/parser/include/cppmetricsparser/cppmetricsparser.h @@ -46,10 +46,10 @@ class CppMetricsParser : public AbstractParser // Used in relational cohesion metric. template void checkTypes( - const std::string path, + const std::string& path, const std::unordered_set& typesFound, const std::unordered_map& typeDefinitionPaths, - std::unordered_map>& relationsFoundInFile, + std::unordered_multimap& relationsFoundInFile, int& relationsInModule ); diff --git a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp index f87e54713..2031de470 100644 --- a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp +++ b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include namespace cc { @@ -170,10 +170,10 @@ void CppMetricsParser::functionBumpyRoad() template void CppMetricsParser::checkTypes( - const std::string path, + const std::string& path, const std::unordered_set& typesFound, - const std::unordered_map& typeDefinitionPaths, - std::unordered_map>& relationsFoundInFile, + const std::unordered_map& typeDefinitionPaths, + std::unordered_multimap& relationsFoundInFile, int& relationsInModule ) { @@ -181,144 +181,140 @@ void CppMetricsParser::checkTypes( : _ctx.db->query( odb::query::query_columns::File::path.like(path + "%") )) - { - if ( - typesFound.find(item.typeHash) != typesFound.end() && - //check if return type is defined within the current module - typeDefinitionPaths.at(item.typeHash) != item.filePath && - //check for self relation - (relationsFoundInFile.find(item.filePath) == relationsFoundInFile.end() || - //check if any reletaions were found in the current file - relationsFoundInFile[item.filePath].find(item.typeHash) == relationsFoundInFile[item.filePath].end()) - //check if this relation is already found + { + if ( + typesFound.find(item.typeHash) != typesFound.end() && + // Check if return type is defined within the current module + typeDefinitionPaths.at(item.typeHash) != item.filePath && + // Check for self relation + relationsFoundInFile.find(item.filePath) == relationsFoundInFile.end() && + // Check if any relations were found in the current file + std::none_of( + relationsFoundInFile.equal_range(item.filePath).first, + relationsFoundInFile.equal_range(item.filePath).second, + [&item](const auto& pair) { return pair.second == item.typeHash; } ) - { - ++relationsInModule; - auto it = relationsFoundInFile.find(item.filePath); - if (it != relationsFoundInFile.end()) - { - it->second.insert(item.typeHash); - } - else - { - relationsFoundInFile.insert(std::make_pair(item.filePath,std::unordered_set{item.typeHash})); - } - } + ) + { + ++relationsInModule; + relationsFoundInFile.emplace(item.filePath, item.typeHash); + LOG(info) << item.filePath; } + } } void CppMetricsParser::relationalCohesion() { - std::unordered_set filepaths; - std::unordered_map typeDefinitionPaths; + std::unordered_set modulePaths; + std::unordered_map typeDefinitionPaths; std::unordered_set typesFound; - std::unordered_map moduleIds; - - util::OdbTransaction {_ctx.db} ([&, this] - { + std::unordered_map moduleIds; + util::OdbTransaction{_ctx.db}([&, this] { std::ifstream file(_modulesPath); - //read the specified module list if given + // Read the specified module list if given if (file.is_open()) { std::string line; - while (std::getline(file,line)) + while (std::getline(file, line)) { - filepaths.insert(line); + modulePaths.insert(line); } } - //if no modules list is specified every directory under the input paths is considered one + // If no modules list is specified every directory under the input paths is considered one else { - for (const auto &inputPath : _inputPaths) + for (const auto& inputPath : _inputPaths) { for (const model::RelationalCohesionFileView& file - : _ctx.db->query( - odb::query::query_columns::path.like(inputPath + "%") && - odb::query::query_columns::type.equal("DIR") - )) + : _ctx.db->query( + odb::query::query_columns::path.like(inputPath + "%") && + odb::query::query_columns::type.equal(model::File::DIRECTORY_TYPE) + )) { - filepaths.insert(file.filePath); - } + modulePaths.insert(file.filePath); + } } } - //get the file IDs for each module - for (auto &path : filepaths) + // Get the file IDs for each module + for (auto& path : modulePaths) { for (const model::RelationalCohesionFileView& file : _ctx.db->query( - odb::query::query_columns::path.like(path) + odb::query::query_columns::path.equal(path) )) - { - moduleIds[file.filePath] = file.fileId; - } + { + moduleIds[file.filePath] = file.fileId; + } } - for (const auto &path : filepaths) + for (const auto& path : modulePaths) { - typesFound.clear(); typeDefinitionPaths.clear(); - //find the types defined in the module + // Find the types defined in the module for (const model::RelationalCohesionRecordView& record - : _ctx.db->query( - odb::query::query_columns::File::path.like(path + "%") - )) + : _ctx.db->query( + odb::query::query_columns::File::path.like(path + "%") + )) { - typesFound.insert(record.typeHash); //save types defined inside the module - typeDefinitionPaths.insert(std::make_pair(record.typeHash,record.filePath)); //save where the type is defined to avoid self relation + // Save types defined inside the module + typesFound.insert(record.typeHash); + // Save where the type is defined to avoid self relation + typeDefinitionPaths.insert(std::make_pair(record.typeHash, record.filePath)); } - - std::unordered_map> relationsFoundInFile; //store the type relations already found for each file + + // Store the type relations already found for each file + std::unordered_multimap relationsFoundInFile; int relationsInModule = 0; - //check function return types + // Check function return types CppMetricsParser::checkTypes( path, typesFound, typeDefinitionPaths, relationsFoundInFile, relationsInModule - ); + ); - //check function parameters + // Check function parameters CppMetricsParser::checkTypes( path, typesFound, typeDefinitionPaths, relationsFoundInFile, relationsInModule - ); + ); - //check function locals + // Check function locals CppMetricsParser::checkTypes( path, typesFound, typeDefinitionPaths, relationsFoundInFile, relationsInModule - ); + ); - //check variables + // Check variables CppMetricsParser::checkTypes( path, typesFound, typeDefinitionPaths, relationsFoundInFile, relationsInModule - ); - - //calculate relational cohesion for module - //formula: H = (R + 1)/ N - //where H is the relational cohesion value, - //R is the number of relationships internal to the module, - //N is the number of types in the module + ); + + // Calculate relational cohesion for module + // Formula: H = (R + 1)/ N + // Where H is the relational cohesion value, + // R is the number of relationships internal to the module, + // N is the number of types in the module uint numberOfTypesInModule = typesFound.size(); //N - double relationalCohesion = + double relationalCohesion = (static_cast(relationsInModule) + 1.0) / static_cast(numberOfTypesInModule); model::CppFileMetrics relationalCohesionMetrics; @@ -326,12 +322,11 @@ void CppMetricsParser::relationalCohesion() relationalCohesionMetrics.value = relationalCohesion; relationalCohesionMetrics.type = model::CppFileMetrics::Type::RELATIONAL_COHESION; _ctx.db->persist(relationalCohesionMetrics); - } - }); } + void CppMetricsParser::lackOfCohesion() { util::OdbTransaction {_ctx.db} ([&, this] diff --git a/plugins/cpp_metrics/test/sources/parser/CMakeLists.txt b/plugins/cpp_metrics/test/sources/parser/CMakeLists.txt index 83409bc33..ec2e3afba 100644 --- a/plugins/cpp_metrics/test/sources/parser/CMakeLists.txt +++ b/plugins/cpp_metrics/test/sources/parser/CMakeLists.txt @@ -4,4 +4,9 @@ project(CppMetricsTestProject) add_library(CppMetricsTestProject STATIC mccabe.cpp lackofcohesion.cpp - bumpyroad.cpp) + bumpyroad.cpp + RelationalCohesion/OneTypeInModule/singleTypeInModule.cpp + RelationalCohesion/MultipleTypesInModuleNoRelation/A.cpp + RelationalCohesion/MultipleTypesInModuleNoRelation/B.cpp + RelationalCohesion/MultipleTypesInModuleNoRelation/C.cpp + RelationalCohesion/MultipleTypesInModuleNoRelation/D.cpp) diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/A.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/A.cpp new file mode 100644 index 000000000..d0d01ec10 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/A.cpp @@ -0,0 +1 @@ +class A {}; diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/B.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/B.cpp new file mode 100644 index 000000000..52971a35f --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/B.cpp @@ -0,0 +1 @@ +class B {}; diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/C.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/C.cpp new file mode 100644 index 000000000..07868b486 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/C.cpp @@ -0,0 +1 @@ +class C {}; diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/D.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/D.cpp new file mode 100644 index 000000000..60fc75c0c --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/D.cpp @@ -0,0 +1 @@ +class D {}; diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/A.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/A.cpp new file mode 100644 index 000000000..ba13f7afd --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/A.cpp @@ -0,0 +1,3 @@ +#include + +void A::f(B par_B, C par_C, D par_D) {} \ No newline at end of file diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/A.h b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/A.h new file mode 100644 index 000000000..fdf4f9c2b --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/A.h @@ -0,0 +1,13 @@ +#ifndef A_H +#define A_H + +#include +#include +#include + +struct A +{ + void f(B par_B, C par_C, D par_D); +}; + +#endif \ No newline at end of file diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/B.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/B.cpp new file mode 100644 index 000000000..8bd7ccc1f --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/B.cpp @@ -0,0 +1,3 @@ +#include + +void B::f(A par_A, C par_C, D par_D) {} \ No newline at end of file diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/B.h b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/B.h new file mode 100644 index 000000000..63d1b6272 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/B.h @@ -0,0 +1,14 @@ +#ifndef B_H +#define B_H + +#include +#include +#include + +struct B +{ + void f(A par_A, C par_C, D par_D); + +}; + +#endif \ No newline at end of file diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/C.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/C.cpp new file mode 100644 index 000000000..49c0d734c --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/C.cpp @@ -0,0 +1,3 @@ +#include + +int C::f(D par_D) {return 0;} \ No newline at end of file diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/C.h b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/C.h new file mode 100644 index 000000000..8cc42f545 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/C.h @@ -0,0 +1,13 @@ +#ifndef C_H +#define C_H + +#include +#include +#include + +struct C +{ + int f(D par_D); +}; + +#endif \ No newline at end of file diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/D.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/D.cpp new file mode 100644 index 000000000..60fc75c0c --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/D.cpp @@ -0,0 +1 @@ +class D {}; diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/D.h b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/D.h new file mode 100644 index 000000000..6566fae60 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/D.h @@ -0,0 +1,6 @@ +#ifndef D_H +#define D_H + +struct D {}; + +#endif diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/OneTypeInModule/singleTypeInModule.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/OneTypeInModule/singleTypeInModule.cpp new file mode 100644 index 000000000..a650fd681 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/OneTypeInModule/singleTypeInModule.cpp @@ -0,0 +1 @@ +class A {}; \ No newline at end of file diff --git a/plugins/cpp_metrics/test/src/cppmetricsparsertest.cpp b/plugins/cpp_metrics/test/src/cppmetricsparsertest.cpp index e22f26d68..6fa2e168f 100644 --- a/plugins/cpp_metrics/test/src/cppmetricsparsertest.cpp +++ b/plugins/cpp_metrics/test/src/cppmetricsparsertest.cpp @@ -13,6 +13,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -231,3 +235,43 @@ INSTANTIATE_TEST_SUITE_P( ParameterizedLackOfCohesionTest, ::testing::ValuesIn(paramLackOfCohesion) ); + + +// Relational cohesion +struct RelationalCohesionParam +{ + std::string moduleName; + double rc; +}; + +class ParameterizedRelationalCohesionTest + : public CppMetricsParserTest, + public ::testing::WithParamInterface +{}; + +std::vector paramRelationalCohesion = { + {"OneTypeInModule", 1.0} + // {"MultipleTypesInModuleNoRelation", 0.25} +}; + +TEST_P(ParameterizedRelationalCohesionTest, RelationalCohesionTest) { + _transaction([&, this](){ + const std::string& moduleName = GetParam().moduleName; + std::uint64_t moduleId = _db->query_value( + !odb::query::path.like("%/CMakeFiles/%") && + odb::query::filename == moduleName).id; + double storedValue = _db->query_value( + odb::query::file == moduleId && + odb::query::type == model::CppFileMetrics::Type::RELATIONAL_COHESION + ).value; + + constexpr double tolerance = 1e-8; + EXPECT_EQF(GetParam().rc, storedValue, tolerance); + }); +} + +INSTANTIATE_TEST_SUITE_P( + ParameterizedRelationalCohesionTestSuite, + ParameterizedRelationalCohesionTest, + ::testing::ValuesIn(paramRelationalCohesion) +); \ No newline at end of file From 4a181892600435725f1380cac632324fb30f98f5 Mon Sep 17 00:00:00 2001 From: Klein Kristof Date: Sun, 7 Jul 2024 09:47:53 +0200 Subject: [PATCH 14/15] Added unit test data --- .../parser/src/cppmetricsparser.cpp | 20 +++++++++++++++++++ .../test/sources/parser/CMakeLists.txt | 8 +++----- .../MultipleTypesInModuleNoRelation/A.cpp | 1 - .../MultipleTypesInModuleNoRelation/B.cpp | 1 - .../MultipleTypesInModuleNoRelation/C.cpp | 1 - .../MultipleTypesInModuleNoRelation/D.cpp | 1 - .../unrelatedA.cpp | 1 + .../unrelatedB.cpp | 1 + .../unrelatedC.cpp | 1 + .../unrelatedD.cpp | 1 + .../RelationByFunctionParameter/A.cpp | 3 --- .../RelationByFunctionParameter/A.h | 13 ------------ .../RelationByFunctionParameter/B.cpp | 3 --- .../RelationByFunctionParameter/B.h | 14 ------------- .../RelationByFunctionParameter/C.cpp | 3 --- .../RelationByFunctionParameter/C.h | 13 ------------ .../RelationByFunctionParameter/D.cpp | 1 - .../RelationByFunctionParameter/D.h | 6 ------ .../relatedByFPA.cpp | 6 ++++++ .../relatedByFPA.h | 14 +++++++++++++ .../relatedByFPB.cpp | 6 ++++++ .../relatedByFPB.h | 14 +++++++++++++ .../relatedByFPC.cpp | 8 ++++++++ .../relatedByFPC.h | 14 +++++++++++++ .../relatedByFPD.cpp | 1 + .../relatedByFPD.h | 6 ++++++ .../relatedByFRA.cpp | 8 ++++++++ .../relatedByFRA.h | 16 +++++++++++++++ .../relatedByFRB.cpp | 8 ++++++++ .../relatedByFRB.h | 16 +++++++++++++++ .../relatedByFRC.cpp | 6 ++++++ .../relatedByFRC.h | 13 ++++++++++++ .../relatedByFRD.cpp | 3 +++ .../relatedByFRD.h | 9 +++++++++ .../RelationByVariable/relatedByVarA.cpp | 6 ++++++ .../RelationByVariable/relatedByVarA.h | 16 +++++++++++++++ .../RelationByVariable/relatedByVarB.cpp | 5 +++++ .../RelationByVariable/relatedByVarB.h | 14 +++++++++++++ .../RelationByVariable/relatedByVarC.cpp | 4 ++++ .../RelationByVariable/relatedByVarC.h | 10 ++++++++++ .../RelationByVariable/relatedByVarD.cpp | 3 +++ .../RelationByVariable/relatedByVarD.h | 9 +++++++++ .../test/src/cppmetricsparsertest.cpp | 5 ++++- 43 files changed, 246 insertions(+), 66 deletions(-) delete mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/A.cpp delete mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/B.cpp delete mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/C.cpp delete mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/D.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/unrelatedA.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/unrelatedB.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/unrelatedC.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/unrelatedD.cpp delete mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/A.cpp delete mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/A.h delete mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/B.cpp delete mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/B.h delete mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/C.cpp delete mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/C.h delete mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/D.cpp delete mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/D.h create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPA.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPA.h create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPB.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPB.h create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPC.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPC.h create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPD.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPD.h create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRA.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRA.h create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRB.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRB.h create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRC.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRC.h create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRD.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRD.h create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarA.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarA.h create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarB.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarB.h create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarC.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarC.h create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarD.cpp create mode 100644 plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarD.h diff --git a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp index 2031de470..70790af97 100644 --- a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp +++ b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp @@ -199,6 +199,7 @@ void CppMetricsParser::checkTypes( ++relationsInModule; relationsFoundInFile.emplace(item.filePath, item.typeHash); LOG(info) << item.filePath; + LOG(info) << relationsInModule; } } } @@ -252,6 +253,10 @@ void CppMetricsParser::relationalCohesion() for (const auto& path : modulePaths) { + + LOG(info) << "looking at module:"; + LOG(info) << path; + typesFound.clear(); typeDefinitionPaths.clear(); // Find the types defined in the module @@ -262,8 +267,20 @@ void CppMetricsParser::relationalCohesion() { // Save types defined inside the module typesFound.insert(record.typeHash); + LOG(info) << "typesFound incremented with: "; + LOG(info) << record.qualifiedName; + LOG(info) << record.typeHash; // Save where the type is defined to avoid self relation typeDefinitionPaths.insert(std::make_pair(record.typeHash, record.filePath)); + + LOG(info) << "Content of types found:"; + + for (auto &&i : typesFound) + { + LOG(info) << i; + } + + } // Store the type relations already found for each file @@ -314,6 +331,9 @@ void CppMetricsParser::relationalCohesion() uint numberOfTypesInModule = typesFound.size(); //N + LOG(info) << relationsInModule; + LOG(info) << numberOfTypesInModule; + double relationalCohesion = (static_cast(relationsInModule) + 1.0) / static_cast(numberOfTypesInModule); diff --git a/plugins/cpp_metrics/test/sources/parser/CMakeLists.txt b/plugins/cpp_metrics/test/sources/parser/CMakeLists.txt index ec2e3afba..79a9771b6 100644 --- a/plugins/cpp_metrics/test/sources/parser/CMakeLists.txt +++ b/plugins/cpp_metrics/test/sources/parser/CMakeLists.txt @@ -1,12 +1,10 @@ cmake_minimum_required(VERSION 2.6) project(CppMetricsTestProject) +file(GLOB_RECURSE RELATIONAL_COHESION_SOURCES "RelationalCohesion/**/*.cpp") + add_library(CppMetricsTestProject STATIC mccabe.cpp lackofcohesion.cpp bumpyroad.cpp - RelationalCohesion/OneTypeInModule/singleTypeInModule.cpp - RelationalCohesion/MultipleTypesInModuleNoRelation/A.cpp - RelationalCohesion/MultipleTypesInModuleNoRelation/B.cpp - RelationalCohesion/MultipleTypesInModuleNoRelation/C.cpp - RelationalCohesion/MultipleTypesInModuleNoRelation/D.cpp) + ${RELATIONAL_COHESION_SOURCES}) diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/A.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/A.cpp deleted file mode 100644 index d0d01ec10..000000000 --- a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/A.cpp +++ /dev/null @@ -1 +0,0 @@ -class A {}; diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/B.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/B.cpp deleted file mode 100644 index 52971a35f..000000000 --- a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/B.cpp +++ /dev/null @@ -1 +0,0 @@ -class B {}; diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/C.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/C.cpp deleted file mode 100644 index 07868b486..000000000 --- a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/C.cpp +++ /dev/null @@ -1 +0,0 @@ -class C {}; diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/D.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/D.cpp deleted file mode 100644 index 60fc75c0c..000000000 --- a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/D.cpp +++ /dev/null @@ -1 +0,0 @@ -class D {}; diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/unrelatedA.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/unrelatedA.cpp new file mode 100644 index 000000000..d1f190669 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/unrelatedA.cpp @@ -0,0 +1 @@ +class unrelatedA {}; diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/unrelatedB.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/unrelatedB.cpp new file mode 100644 index 000000000..27b374dfc --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/unrelatedB.cpp @@ -0,0 +1 @@ +class unrelatedB {}; diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/unrelatedC.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/unrelatedC.cpp new file mode 100644 index 000000000..17350c663 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/unrelatedC.cpp @@ -0,0 +1 @@ +class unrelatedC {}; diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/unrelatedD.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/unrelatedD.cpp new file mode 100644 index 000000000..b5a3d8f55 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleNoRelation/unrelatedD.cpp @@ -0,0 +1 @@ +class unrelatedD {}; diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/A.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/A.cpp deleted file mode 100644 index ba13f7afd..000000000 --- a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/A.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include - -void A::f(B par_B, C par_C, D par_D) {} \ No newline at end of file diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/A.h b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/A.h deleted file mode 100644 index fdf4f9c2b..000000000 --- a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/A.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef A_H -#define A_H - -#include -#include -#include - -struct A -{ - void f(B par_B, C par_C, D par_D); -}; - -#endif \ No newline at end of file diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/B.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/B.cpp deleted file mode 100644 index 8bd7ccc1f..000000000 --- a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/B.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include - -void B::f(A par_A, C par_C, D par_D) {} \ No newline at end of file diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/B.h b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/B.h deleted file mode 100644 index 63d1b6272..000000000 --- a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/B.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef B_H -#define B_H - -#include -#include -#include - -struct B -{ - void f(A par_A, C par_C, D par_D); - -}; - -#endif \ No newline at end of file diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/C.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/C.cpp deleted file mode 100644 index 49c0d734c..000000000 --- a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/C.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include - -int C::f(D par_D) {return 0;} \ No newline at end of file diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/C.h b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/C.h deleted file mode 100644 index 8cc42f545..000000000 --- a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/C.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef C_H -#define C_H - -#include -#include -#include - -struct C -{ - int f(D par_D); -}; - -#endif \ No newline at end of file diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/D.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/D.cpp deleted file mode 100644 index 60fc75c0c..000000000 --- a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/D.cpp +++ /dev/null @@ -1 +0,0 @@ -class D {}; diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/D.h b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/D.h deleted file mode 100644 index 6566fae60..000000000 --- a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/D.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef D_H -#define D_H - -struct D {}; - -#endif diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPA.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPA.cpp new file mode 100644 index 000000000..ddd6130ae --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPA.cpp @@ -0,0 +1,6 @@ +#include "relatedByFPA.h" +#include "relatedByFPB.h" +#include "relatedByFPC.h" +#include "relatedByFPD.h" + +void relatedByFPA::f(relatedByFPB par_B, relatedByFPC par_C, relatedByFPD par_D) {} diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPA.h b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPA.h new file mode 100644 index 000000000..260c8b9c7 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPA.h @@ -0,0 +1,14 @@ +#ifndef relatedByFPA_H +#define relatedByFPA_H + +// Forward declarations +class relatedByFPB; +class relatedByFPC; +class relatedByFPD; + +class relatedByFPA { +public: + void f(relatedByFPB par_B, relatedByFPC par_C, relatedByFPD par_D); +}; + +#endif diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPB.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPB.cpp new file mode 100644 index 000000000..7cc6703c9 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPB.cpp @@ -0,0 +1,6 @@ +#include "relatedByFPB.h" +#include "relatedByFPA.h" +#include "relatedByFPC.h" +#include "relatedByFPD.h" + +void relatedByFPB::f(relatedByFPA par_A, relatedByFPC par_C, relatedByFPD par_D) {} diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPB.h b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPB.h new file mode 100644 index 000000000..bc7a22e89 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPB.h @@ -0,0 +1,14 @@ +#ifndef relatedByFPB_H +#define relatedByFPB_H + +// Forward declarations +class relatedByFPA; +class relatedByFPC; +class relatedByFPD; + +class relatedByFPB { +public: + void f(relatedByFPA par_A, relatedByFPC par_C, relatedByFPD par_D); +}; + +#endif diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPC.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPC.cpp new file mode 100644 index 000000000..f5c50b6b7 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPC.cpp @@ -0,0 +1,8 @@ +#include "relatedByFPC.h" +#include "relatedByFPA.h" +#include "relatedByFPB.h" +#include "relatedByFPD.h" + +int relatedByFPC::f(relatedByFPD par_D) { + return 0; +} diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPC.h b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPC.h new file mode 100644 index 000000000..d19487181 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPC.h @@ -0,0 +1,14 @@ +#ifndef relatedByFPC_H +#define relatedByFPC_H + +// Forward declarations +class relatedByFPA; +class relatedByFPB; +class relatedByFPD; + +class relatedByFPC { +public: + int f(relatedByFPD par_D); +}; + +#endif diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPD.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPD.cpp new file mode 100644 index 000000000..415e1f5e0 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPD.cpp @@ -0,0 +1 @@ +#include "relatedByFPD.h" diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPD.h b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPD.h new file mode 100644 index 000000000..cd38e8c61 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionParameter/relatedByFPD.h @@ -0,0 +1,6 @@ +#ifndef relatedByFPD_H +#define relatedByFPD_H + +class relatedByFPD {}; + +#endif diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRA.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRA.cpp new file mode 100644 index 000000000..31e4049b8 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRA.cpp @@ -0,0 +1,8 @@ +#include "relatedByFRA.h" +#include "relatedByFRB.h" +#include "relatedByFRC.h" +#include "relatedByFRD.h" + +relatedByFRB relatedByFRA::fB() {return relatedByFRB();}; +relatedByFRC relatedByFRA::fC() {return relatedByFRC();}; +relatedByFRD relatedByFRA::fD() {return relatedByFRD();}; diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRA.h b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRA.h new file mode 100644 index 000000000..d19833746 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRA.h @@ -0,0 +1,16 @@ +#ifndef relatedByFRA_H +#define relatedByFRA_H + +class relatedByFRB; +class relatedByFRC; +class relatedByFRD; + +class relatedByFRA { +public: + relatedByFRA() {} + relatedByFRB fB(); + relatedByFRC fC(); + relatedByFRD fD(); +}; + +#endif diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRB.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRB.cpp new file mode 100644 index 000000000..c040a2cf0 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRB.cpp @@ -0,0 +1,8 @@ +#include "relatedByFRA.h" +#include "relatedByFRB.h" +#include "relatedByFRC.h" +#include "relatedByFRD.h" + +relatedByFRA relatedByFRB::fA() {return relatedByFRA();} +relatedByFRC relatedByFRB::fC() {return relatedByFRC();} +relatedByFRD relatedByFRB::fD() {return relatedByFRD();} \ No newline at end of file diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRB.h b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRB.h new file mode 100644 index 000000000..d5b8f802e --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRB.h @@ -0,0 +1,16 @@ +#ifndef relatedByFRB_H +#define relatedByFRB_H + +class relatedByFRA; +class relatedByFRC; +class relatedByFRD; + +class relatedByFRB { +public: + relatedByFRB() {} + relatedByFRA fA(); + relatedByFRC fC(); + relatedByFRD fD(); +}; + +#endif diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRC.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRC.cpp new file mode 100644 index 000000000..83c32d48e --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRC.cpp @@ -0,0 +1,6 @@ +#include "relatedByFRC.h" +#include "relatedByFRA.h" +#include "relatedByFRB.h" +#include "relatedByFRD.h" + +relatedByFRC::relatedByFRC() {} diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRC.h b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRC.h new file mode 100644 index 000000000..dc6eb5907 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRC.h @@ -0,0 +1,13 @@ +#ifndef relatedByFRC_H +#define relatedByFRC_H + +class relatedByFRA; +class relatedByFRB; +class relatedByFRD; + +class relatedByFRC { +public: + relatedByFRC (); +}; + +#endif diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRD.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRD.cpp new file mode 100644 index 000000000..f625a9446 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRD.cpp @@ -0,0 +1,3 @@ +#include "relatedByFRD.h" + +relatedByFRD::relatedByFRD() {} \ No newline at end of file diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRD.h b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRD.h new file mode 100644 index 000000000..7d669e475 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByFunctionReturnValue/relatedByFRD.h @@ -0,0 +1,9 @@ +#ifndef relatedByFRD_H +#define relatedByFRD_H + +class relatedByFRD { + public: + relatedByFRD (); +}; + +#endif diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarA.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarA.cpp new file mode 100644 index 000000000..c97c98532 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarA.cpp @@ -0,0 +1,6 @@ +#include "relatedByVarA.h" +#include "relatedByVarB.h" +#include "relatedByVarC.h" +#include "relatedByVarD.h" + +void relatedByVarA::f() {relatedByVarD* varD;} diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarA.h b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarA.h new file mode 100644 index 000000000..25e367fb3 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarA.h @@ -0,0 +1,16 @@ +#ifndef relatedByVarA_H +#define relatedByVarA_H + +class relatedByVarB; +class relatedByVarC; + +class relatedByVarA { +private: + relatedByVarB* varB; + relatedByVarC* varC; +public: + relatedByVarA() : varB(nullptr), varC(nullptr) {} + void f(); +}; + +#endif diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarB.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarB.cpp new file mode 100644 index 000000000..9a1f9ebb2 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarB.cpp @@ -0,0 +1,5 @@ +#include "relatedByVarA.h" +#include "relatedByVarB.h" +#include "relatedByVarC.h" + +void relatedByVarB::f() {relatedByVarC* varC;} \ No newline at end of file diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarB.h b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarB.h new file mode 100644 index 000000000..b5c6c87f1 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarB.h @@ -0,0 +1,14 @@ +#ifndef relatedByVarB_H +#define relatedByVarB_H + +class relatedByVarA; + +class relatedByVarB { +private: + relatedByVarA* varA; +public: + relatedByVarB() : varA(nullptr) {} + void f(); +}; + +#endif diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarC.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarC.cpp new file mode 100644 index 000000000..571187a6b --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarC.cpp @@ -0,0 +1,4 @@ +#include "relatedByVarA.h" +#include "relatedByVarC.h" + +void relatedByVarC::f() {relatedByVarA* varA;} diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarC.h b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarC.h new file mode 100644 index 000000000..1e826a12f --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarC.h @@ -0,0 +1,10 @@ +#ifndef relatedByVarC_H +#define relatedByVarC_H + +class relatedByVarC { +public: + relatedByVarC() {} + void f(); +}; + +#endif diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarD.cpp b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarD.cpp new file mode 100644 index 000000000..56b4e884f --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarD.cpp @@ -0,0 +1,3 @@ +#include "relatedByVarD.h" + +relatedByVarD::relatedByVarD() {} \ No newline at end of file diff --git a/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarD.h b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarD.h new file mode 100644 index 000000000..4aef34ae6 --- /dev/null +++ b/plugins/cpp_metrics/test/sources/parser/RelationalCohesion/MultipleTypesInModuleWithRelations/RelationByVariable/relatedByVarD.h @@ -0,0 +1,9 @@ +#ifndef relatedByVarD_H +#define relatedByVarD_H + +class relatedByVarD { + public: + relatedByVarD (); +}; + +#endif diff --git a/plugins/cpp_metrics/test/src/cppmetricsparsertest.cpp b/plugins/cpp_metrics/test/src/cppmetricsparsertest.cpp index 6fa2e168f..67d7bbf2e 100644 --- a/plugins/cpp_metrics/test/src/cppmetricsparsertest.cpp +++ b/plugins/cpp_metrics/test/src/cppmetricsparsertest.cpp @@ -251,7 +251,10 @@ class ParameterizedRelationalCohesionTest std::vector paramRelationalCohesion = { {"OneTypeInModule", 1.0} - // {"MultipleTypesInModuleNoRelation", 0.25} + /*{"MultipleTypesInModuleNoRelation", 0.25}, + {"RelationByFunctionParameter", 7.0/4.0}, + {"RelationByFunctionReturnValue", 6.0/4.0}, + {"RelationByVariable", 6.0/4.0}*/ }; TEST_P(ParameterizedRelationalCohesionTest, RelationalCohesionTest) { From e8720ecad3f3101df5557e8967d9bd4c6c95e353 Mon Sep 17 00:00:00 2001 From: Klein Kristof Date: Sun, 7 Jul 2024 09:51:03 +0200 Subject: [PATCH 15/15] Removed unneded logging --- .../parser/src/cppmetricsparser.cpp | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp index 70790af97..ae1e7ec97 100644 --- a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp +++ b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp @@ -198,8 +198,6 @@ void CppMetricsParser::checkTypes( { ++relationsInModule; relationsFoundInFile.emplace(item.filePath, item.typeHash); - LOG(info) << item.filePath; - LOG(info) << relationsInModule; } } } @@ -253,10 +251,6 @@ void CppMetricsParser::relationalCohesion() for (const auto& path : modulePaths) { - - LOG(info) << "looking at module:"; - LOG(info) << path; - typesFound.clear(); typeDefinitionPaths.clear(); // Find the types defined in the module @@ -267,20 +261,8 @@ void CppMetricsParser::relationalCohesion() { // Save types defined inside the module typesFound.insert(record.typeHash); - LOG(info) << "typesFound incremented with: "; - LOG(info) << record.qualifiedName; - LOG(info) << record.typeHash; // Save where the type is defined to avoid self relation typeDefinitionPaths.insert(std::make_pair(record.typeHash, record.filePath)); - - LOG(info) << "Content of types found:"; - - for (auto &&i : typesFound) - { - LOG(info) << i; - } - - } // Store the type relations already found for each file @@ -331,9 +313,6 @@ void CppMetricsParser::relationalCohesion() uint numberOfTypesInModule = typesFound.size(); //N - LOG(info) << relationsInModule; - LOG(info) << numberOfTypesInModule; - double relationalCohesion = (static_cast(relationsInModule) + 1.0) / static_cast(numberOfTypesInModule);