From de4ce6fcb6fef73e3439f56bb06192773ccd7f17 Mon Sep 17 00:00:00 2001 From: bruntib Date: Fri, 31 Jul 2020 14:54:03 +0200 Subject: [PATCH] Adding C++ compiler diagnostic messages to the database (#403) Adding diagnostic messages to the database. clang::DiagnosticConsumer is handling the diagnostic messages (compilation errors, warnings, notes, etc.) during C/C++ compilation. These diagnostic messages are collected and stored in the database. --- model/include/model/buildlog.h | 4 - plugins/cpp/parser/CMakeLists.txt | 3 +- .../parser/include/cppparser/filelocutil.h | 2 +- plugins/cpp/parser/src/cppparser.cpp | 4 + .../parser/src/diagnosticmessagehandler.cpp | 75 +++++++++++++++++++ .../cpp/parser/src/diagnosticmessagehandler.h | 35 +++++++++ 6 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 plugins/cpp/parser/src/diagnosticmessagehandler.cpp create mode 100644 plugins/cpp/parser/src/diagnosticmessagehandler.h diff --git a/model/include/model/buildlog.h b/model/include/model/buildlog.h index 0fbcb531f..981d3d308 100644 --- a/model/include/model/buildlog.h +++ b/model/include/model/buildlog.h @@ -43,10 +43,6 @@ struct BuildLog #pragma db not_null BuildLogMessage log; - #pragma db not_null - #pragma db on_delete(cascade) - std::shared_ptr action; - #pragma db null FileLoc location; }; diff --git a/plugins/cpp/parser/CMakeLists.txt b/plugins/cpp/parser/CMakeLists.txt index ef96579ca..0f02bd096 100644 --- a/plugins/cpp/parser/CMakeLists.txt +++ b/plugins/cpp/parser/CMakeLists.txt @@ -35,7 +35,8 @@ add_library(cppparser SHARED src/ppincludecallback.cpp src/ppmacrocallback.cpp src/relationcollector.cpp - src/doccommentformatter.cpp) + src/doccommentformatter.cpp + src/diagnosticmessagehandler.cpp) target_link_libraries(cppparser cppmodel diff --git a/plugins/cpp/parser/include/cppparser/filelocutil.h b/plugins/cpp/parser/include/cppparser/filelocutil.h index 7f5546bf5..ccfa96883 100644 --- a/plugins/cpp/parser/include/cppparser/filelocutil.h +++ b/plugins/cpp/parser/include/cppparser/filelocutil.h @@ -85,7 +85,7 @@ class FileLocUtil */ std::string getFilePath(const clang::SourceLocation& loc_) { - clang::SourceLocation expLoc =_clangSrcMan.getExpansionLoc(loc_); + clang::SourceLocation expLoc = _clangSrcMan.getExpansionLoc(loc_); clang::FileID fid = _clangSrcMan.getFileID(expLoc); if (fid.isInvalid()) diff --git a/plugins/cpp/parser/src/cppparser.cpp b/plugins/cpp/parser/src/cppparser.cpp index 19c2eb641..2cbc0b0a0 100644 --- a/plugins/cpp/parser/src/cppparser.cpp +++ b/plugins/cpp/parser/src/cppparser.cpp @@ -35,6 +35,7 @@ #include "ppincludecallback.h" #include "ppmacrocallback.h" #include "doccommentcollector.h" +#include "diagnosticmessagehandler.h" namespace cc { @@ -325,6 +326,9 @@ int CppParser::parseWorker(const clang::tooling::CompileCommand& command_) VisitorActionFactory factory(_ctx); clang::tooling::ClangTool tool(*compilationDb, command_.Filename); + DiagnosticMessageHandler diagMsgHandler(_ctx.srcMgr, _ctx.db); + tool.setDiagnosticConsumer(&diagMsgHandler); + int error = tool.run(&factory); //--- Save build command ---// diff --git a/plugins/cpp/parser/src/diagnosticmessagehandler.cpp b/plugins/cpp/parser/src/diagnosticmessagehandler.cpp new file mode 100644 index 000000000..db523e653 --- /dev/null +++ b/plugins/cpp/parser/src/diagnosticmessagehandler.cpp @@ -0,0 +1,75 @@ +#include +#include +#include "diagnosticmessagehandler.h" + +namespace cc +{ +namespace parser +{ + +DiagnosticMessageHandler::DiagnosticMessageHandler( + SourceManager& srcMgr_, + std::shared_ptr db_) + : _srcMgr(srcMgr_), _db(db_) +{ +} + +void DiagnosticMessageHandler::HandleDiagnostic( + clang::DiagnosticsEngine::Level diagLevel_, + const clang::Diagnostic& info_) +{ + clang::DiagnosticConsumer::HandleDiagnostic(diagLevel_, info_); + + model::BuildLog buildLog; + + //--- Message type ---// + + switch (diagLevel_) + { + case clang::DiagnosticsEngine::Note: + buildLog.log.type = model::BuildLogMessage::Note; + break; + case clang::DiagnosticsEngine::Warning: + buildLog.log.type = model::BuildLogMessage::Warning; + break; + case clang::DiagnosticsEngine::Error: + buildLog.log.type = model::BuildLogMessage::Error; + break; + case clang::DiagnosticsEngine::Fatal: + buildLog.log.type = model::BuildLogMessage::FatalError; + break; + } + + //--- Message content ---// + + llvm::SmallString<512> content; + info_.FormatDiagnostic(content); + buildLog.log.message = content.c_str(); + + //--- Message location ---// + + if (info_.getLocation().isValid() && info_.hasSourceManager()) + { + FileLocUtil fileLocUtil(info_.getSourceManager()); + const clang::SourceLocation& loc = info_.getLocation(); + + model::Range fileLoc; + fileLocUtil.setRange(loc, loc, fileLoc); + + buildLog.location.range = fileLoc; + buildLog.location.file = _srcMgr.getFile(fileLocUtil.getFilePath(loc)); + } + + _messages.push_back(buildLog); +} + +DiagnosticMessageHandler::~DiagnosticMessageHandler() +{ + util::OdbTransaction{_db}([this](){ + for (model::BuildLog& message : _messages) + _db->persist(message); + }); +} + +} +} diff --git a/plugins/cpp/parser/src/diagnosticmessagehandler.h b/plugins/cpp/parser/src/diagnosticmessagehandler.h new file mode 100644 index 000000000..d210b262d --- /dev/null +++ b/plugins/cpp/parser/src/diagnosticmessagehandler.h @@ -0,0 +1,35 @@ +#ifndef CC_PARSER_DIAGNOSTICMESSAGEHANDLER_H +#define CC_PARSER_DIAGNOSTICMESSAGEHANDLER_H + +#include +#include +#include +#include + +namespace cc +{ +namespace parser +{ + +class DiagnosticMessageHandler : public clang::DiagnosticConsumer +{ +public: + DiagnosticMessageHandler( + SourceManager& srcMgr_, + std::shared_ptr db_); + ~DiagnosticMessageHandler(); + + void HandleDiagnostic( + clang::DiagnosticsEngine::Level diagLevel_, + const clang::Diagnostic& info_) override; + +private: + SourceManager& _srcMgr; + std::vector _messages; + std::shared_ptr _db; +}; + +} +} + +#endif