From 251eab6e9edf3cc75cf09d878c5fd12be0c76a84 Mon Sep 17 00:00:00 2001 From: Andreas Stallinger Date: Wed, 31 Aug 2016 14:37:28 +0200 Subject: [PATCH] ui: prefill headers from compilation database dialog for selecting header paths from compilation database --- bin/app/data/gui/window/window.css | 2 +- setup/git/git_pre_commit_hook.sh | 14 +--- src/app/CMakeLists.txt | 4 +- src/app/utility/CompilationDatabase.cpp | 69 +++++++++++++++ src/lib/CMakeLists.txt | 1 + src/lib/utility/CompilationDatabase.h | 31 +++++++ src/lib/utility/file/FilePath.cpp | 7 ++ src/lib/utility/file/FilePath.h | 1 + src/lib_gui/CMakeLists.txt | 2 + src/lib_gui/qt/window/QtSelectPathsDialog.cpp | 83 +++++++++++++++++++ src/lib_gui/qt/window/QtSelectPathsDialog.h | 25 ++++++ src/lib_gui/qt/window/QtTextEditDialog.h | 3 +- .../project_wizzard/QtProjectWizzard.cpp | 4 +- .../project_wizzard/QtProjectWizzardContent.h | 6 +- .../QtProjectWizzardContentPaths.cpp | 53 ++++++++++++ .../QtProjectWizzardContentPaths.h | 13 ++- src/lib_parser/CMakeLists.txt | 4 +- src/trial/CMakeLists.txt | 4 +- src/trial/utility/CompilationDatabase.cpp | 38 +++++++++ 19 files changed, 337 insertions(+), 27 deletions(-) create mode 100644 src/app/utility/CompilationDatabase.cpp create mode 100644 src/lib/utility/CompilationDatabase.h create mode 100644 src/lib_gui/qt/window/QtSelectPathsDialog.cpp create mode 100644 src/lib_gui/qt/window/QtSelectPathsDialog.h create mode 100644 src/trial/utility/CompilationDatabase.cpp diff --git a/bin/app/data/gui/window/window.css b/bin/app/data/gui/window/window.css index 230813bc..a5a667f3 100644 --- a/bin/app/data/gui/window/window.css +++ b/bin/app/data/gui/window/window.css @@ -171,7 +171,7 @@ QLabel, QCheckBox { background: #CFD2E0; } -#textField { +#textField, #pathList { background: white; border: 1px solid lightgray; border-radius: 12px; diff --git a/setup/git/git_pre_commit_hook.sh b/setup/git/git_pre_commit_hook.sh index 33b00b4d..8dbc8ae8 100755 --- a/setup/git/git_pre_commit_hook.sh +++ b/setup/git/git_pre_commit_hook.sh @@ -20,24 +20,16 @@ elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then PLATFORM='Windows' fi -function fallback { - FALLBACK_BRANCH=${BRANCH_NAME:3} - FALLBACK_BRANCH="${FALLBACK_BRANCH%?}" - git checkout ${FALLBACK_BRANCH} - git branch -D ${BRANCH_NAME} -} - function build { echo -e $INFO Building $1 \($2\) - cmake --build build/$2 --target $1 > /dev/null + #cmake --build build/$2 --target $1 > /dev/null #output to commandline for debugging - #cmake --build build/$2 --target $1 + cmake --build build/$2 --target $1 if [ $? -eq 0 ] then echo -e $PASS Building $1 \($2\) passed else echo -e $FAIL Building $1 \($2\) failed - fallback exit 1 fi } @@ -51,7 +43,6 @@ function build_type { if [ $? -ne 0 ] then echo -e $FAIL At least one build or test failed, no push to $branch - fallback exit 1 fi else @@ -74,7 +65,6 @@ function run_tests { echo -e $PASS $1 Tests passed else echo -e $FAIL $1 Tests failed - fallback exit 1 fi cd $ROOTDIR diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index 2f8af48c..a71686dc 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -3,12 +3,14 @@ add_files( data/parser/cxx/TaskParseCxx.cpp data/parser/cxx/TaskParseWrapper.cpp - + data/parser/java/TaskParseJava.cpp utility/commandline/CommandLineParser.cpp utility/commandline/CommandLineParser.h + utility/CompilationDatabase.cpp + isTrial.cpp main.cpp ) diff --git a/src/app/utility/CompilationDatabase.cpp b/src/app/utility/CompilationDatabase.cpp new file mode 100644 index 00000000..72bae5cc --- /dev/null +++ b/src/app/utility/CompilationDatabase.cpp @@ -0,0 +1,69 @@ +#include "utility/CompilationDatabase.h" + +#include +#include "utility/utility.h" +#include "clang/Tooling/JSONCompilationDatabase.h" + +utility::CompilationDatabase::CompilationDatabase(std::string filename) + : m_filename(filename) +{ + getHeaders(); +} + +std::vector utility::CompilationDatabase::getAllHeaderPaths() +{ + std::vector paths = utility::concat(m_headers, m_systemHeaders); + paths = utility::concat(paths, m_frameworkHeaders); + paths = utility::unique(paths); + return paths; +} + +std::vector utility::CompilationDatabase::getHeaderPaths() +{ + return m_headers; +} + +std::vector utility::CompilationDatabase::getSystemHeaderPaths() +{ + return m_systemHeaders; +} + +std::vector utility::CompilationDatabase::getFrameworkHeaderPaths() +{ + return m_frameworkHeaders; +} + +void utility::CompilationDatabase::getHeaders() +{ + std::string error; + std::shared_ptr cdb = std::shared_ptr + (clang::tooling::JSONCompilationDatabase::loadFromFile(m_filename, error)); + + std::vector commands = cdb->getAllCompileCommands(); + std::set frameworkHeaders; + std::set systemHeaders; + std::set headers; + + for (clang::tooling::CompileCommand command : commands) + { + for( size_t i = 0; i < command.CommandLine.size(); i++) + { + if( command.CommandLine[i] == "-iframework" ) + { + frameworkHeaders.insert(FilePath(command.CommandLine[++i], command.Directory)); + } + if( command.CommandLine[i] == "-isystem" ) + { + systemHeaders.insert(FilePath(command.CommandLine[++i], command.Directory)); + } + if( command.CommandLine[i].substr(0,2) == "-I" ) + { + headers.insert(FilePath(command.CommandLine[i].substr(2), command.Directory)); + } + } + } + + m_headers = utility::toVector(headers); + m_frameworkHeaders = utility::toVector(frameworkHeaders); + m_systemHeaders = utility::toVector(systemHeaders); +} diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 6e6e17bd..245fa6e4 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -332,6 +332,7 @@ add_files( utility/AppPath.cpp utility/AppPath.h utility/Cache.h + utility/CompilationDatabase.h utility/ConfigManager.cpp utility/ConfigManager.h utility/Property.h diff --git a/src/lib/utility/CompilationDatabase.h b/src/lib/utility/CompilationDatabase.h new file mode 100644 index 00000000..051a17e4 --- /dev/null +++ b/src/lib/utility/CompilationDatabase.h @@ -0,0 +1,31 @@ +#ifndef UTILITY_COMPLIATION_DATABASE_H +#define UTILITY_COMPLIATION_DATABASE_H + +#include + +#include "utility/file/FilePath.h" + +namespace utility +{ + class CompilationDatabase + { + public: + CompilationDatabase(std::string filename); + + std::vector getAllHeaderPaths(); + std::vector getHeaderPaths(); + std::vector getSystemHeaderPaths(); + std::vector getFrameworkHeaderPaths(); + + private: + std::string m_filename; + std::vector m_headers; + std::vector m_systemHeaders; + std::vector m_frameworkHeaders; + + void getHeaders(); + }; + +} + +#endif // UTILITY_COMPLIATION_DATABASE_H diff --git a/src/lib/utility/file/FilePath.cpp b/src/lib/utility/file/FilePath.cpp index 5d7477b1..6dcfcb2d 100644 --- a/src/lib/utility/file/FilePath.cpp +++ b/src/lib/utility/file/FilePath.cpp @@ -32,6 +32,13 @@ FilePath::FilePath(const boost::filesystem::path& filePath) { } +FilePath::FilePath(const std::string& filePath, const std::string& base) + : m_path(boost::filesystem::absolute(filePath, base)) + , m_exists(false) + , m_checkedExists(false) +{ +} + boost::filesystem::path FilePath::path() const { return m_path; diff --git a/src/lib/utility/file/FilePath.h b/src/lib/utility/file/FilePath.h index 7b24b110..45066507 100644 --- a/src/lib/utility/file/FilePath.h +++ b/src/lib/utility/file/FilePath.h @@ -12,6 +12,7 @@ public: FilePath(const char* filePath); FilePath(const std::string& filePath); FilePath(const boost::filesystem::path& filePath); + FilePath(const std::string& filePath, const std::string& base); boost::filesystem::path path() const; diff --git a/src/lib_gui/CMakeLists.txt b/src/lib_gui/CMakeLists.txt index 5301d159..28ac9a17 100644 --- a/src/lib_gui/CMakeLists.txt +++ b/src/lib_gui/CMakeLists.txt @@ -149,6 +149,8 @@ add_files( qt/window/QtLicense.h qt/window/QtMainWindow.cpp qt/window/QtMainWindow.h + qt/window/QtSelectPathsDialog.cpp + qt/window/QtSelectPathsDialog.h qt/window/QtSplashScreen.cpp qt/window/QtSplashScreen.h qt/window/QtStartScreen.cpp diff --git a/src/lib_gui/qt/window/QtSelectPathsDialog.cpp b/src/lib_gui/qt/window/QtSelectPathsDialog.cpp new file mode 100644 index 00000000..160d6538 --- /dev/null +++ b/src/lib_gui/qt/window/QtSelectPathsDialog.cpp @@ -0,0 +1,83 @@ +#include "qt/window/QtSelectPathsDialog.h" + +#include +#include + +QtSelectPathsDialog::QtSelectPathsDialog(const QString& title, const QString& description, QWidget* parent) + : QtTextEditDialog(title, description, parent) +{ +} + +std::vector QtSelectPathsDialog::getPathsList() const +{ + std::vector checkedPaths; + + for (int i = 0; i < m_list->count(); i++) + { + if (m_list->item(i)->checkState() == Qt::Checked) + { + checkedPaths.push_back(m_list->item(i)->text().toStdString()); + } + } + + return checkedPaths; +} + +void QtSelectPathsDialog::setPathsList(const std::vector& paths, const std::vector& checkedPaths) +{ + for (FilePath s : paths) + { + QListWidgetItem* item = new QListWidgetItem(s.str().c_str(), m_list); + item->setFlags(item->flags() | Qt::ItemIsUserCheckable); // set checkable flag + + if (std::find(checkedPaths.begin(), checkedPaths.end(), s) == checkedPaths.end()) + { + item->setCheckState(Qt::Unchecked); // AND initialize check state + } + else + { + item->setCheckState(Qt::Checked); + } + + if (!s.exists()) + { + item->setTextColor(Qt::red); + item->setToolTip("Path does not exist"); + item->setFlags( item->flags() & ~Qt::ItemIsEnabled ); + } + else + { + item->setTextColor(Qt::black); + } + } +} + +void QtSelectPathsDialog::populateWindow(QWidget* widget) +{ + QVBoxLayout* layout = new QVBoxLayout(); + layout->setContentsMargins(0, 0, 0, 0); + + QLabel* description = new QLabel(m_description); + description->setObjectName("description"); + description->setWordWrap(true); + layout->addWidget(description); + + m_list = new QListWidget(); + m_list->setObjectName("pathList"); + m_list->setEditTriggers(QAbstractItemView::NoEditTriggers); + m_list->setSelectionMode(QAbstractItemView::NoSelection); + m_list->setAttribute(Qt::WA_MacShowFocusRect, 0); + layout->addWidget(m_list); + + widget->setLayout(layout); +} + +void QtSelectPathsDialog::windowReady() +{ + updateNextButton("Save"); + updateCloseButton("Cancel"); + + setPreviousVisible(false); + + updateTitle(m_title); +} diff --git a/src/lib_gui/qt/window/QtSelectPathsDialog.h b/src/lib_gui/qt/window/QtSelectPathsDialog.h new file mode 100644 index 00000000..43ab17d8 --- /dev/null +++ b/src/lib_gui/qt/window/QtSelectPathsDialog.h @@ -0,0 +1,25 @@ +#ifndef QT_SELECT_PATHS_DIALOG_H +#define QT_SELECT_PATHS_DIALOG_H + +#include "qt/window/QtTextEditDialog.h" +#include "utility/file/FilePath.h" + +class QListWidget; + +class QtSelectPathsDialog + : public QtTextEditDialog +{ +public: + QtSelectPathsDialog(const QString& title, const QString& description, QWidget* parent = 0); + + std::vector getPathsList() const; + void setPathsList(const std::vector& paths, const std::vector& checkedPaths); + + virtual void populateWindow(QWidget* widget) override; + virtual void windowReady() override; + +private: + QListWidget* m_list; +}; + +#endif // QT_SELECT_PATHS_DIALOG_H diff --git a/src/lib_gui/qt/window/QtTextEditDialog.h b/src/lib_gui/qt/window/QtTextEditDialog.h index 67bb2fb3..49a5293a 100644 --- a/src/lib_gui/qt/window/QtTextEditDialog.h +++ b/src/lib_gui/qt/window/QtTextEditDialog.h @@ -24,10 +24,11 @@ protected: void populateWindow(QWidget* widget) override; void windowReady() override; -private: QString m_title; QString m_description; +private: + QPlainTextEdit* m_text; }; diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzard.cpp b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzard.cpp index eb88659b..14edf37a 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzard.cpp +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzard.cpp @@ -505,9 +505,7 @@ void QtProjectWizzard::showSummary() else { summary->addContent(new QtProjectWizzardContentDataCDB(m_settings, window), false, false); - - QtProjectWizzardContent* headers = new QtProjectWizzardContentPathsCDBHeader(m_settings, window); - summary->addContent(headers, false, true); + summary->addContent(new QtProjectWizzardContentPathsCDBHeader(m_settings, window), false, true); summary->addContent(new QtProjectWizzardContentPathsHeaderSearch(m_settings, window, true), false, true); summary->addContent(new QtProjectWizzardContentPathsHeaderSearchGlobal(m_settings, window), false, false); diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContent.h b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContent.h index 15ff21eb..7eebdf2e 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContent.h +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContent.h @@ -63,13 +63,13 @@ protected: std::shared_ptr m_settings; QtProjectWizzardWindow* m_window; -private slots: + std::shared_ptr m_filesDialog; + +protected slots: void filesButtonClicked(); void closedFilesDialog(); private: - std::shared_ptr m_filesDialog; - bool m_isInForm; }; diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp index 3570abc5..34e033ee 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp @@ -3,11 +3,14 @@ #include #include #include +#include #include "qt/element/QtDirectoryListBox.h" +#include "qt/window/QtSelectPathsDialog.h" #include "settings/ApplicationSettings.h" #include "settings/CxxProjectSettings.h" #include "settings/JavaProjectSettings.h" +#include "utility/CompilationDatabase.h" #include "utility/file/FileManager.h" #include "utility/file/FileSystem.h" #include "utility/path_detector/cxx_header/CxxFrameworkPathDetector.h" @@ -235,6 +238,56 @@ QtProjectWizzardContentPathsCDBHeader::QtProjectWizzardContentPathsCDBHeader( ); } +void QtProjectWizzardContentPathsCDBHeader::populate( QGridLayout* layout, int& row) +{ + QtProjectWizzardContentPaths::populate(layout, row); + + QPushButton* button = new QPushButton("Select from Include Paths"); + button->setObjectName("windowButton"); + connect(button, SIGNAL(clicked()), this, SLOT(buttonClicked())); + + layout->addWidget(button, row, QtProjectWizzardWindow::BACK_COL, Qt::AlignRight | Qt::AlignTop); + row++; +} + +void QtProjectWizzardContentPathsCDBHeader::buttonClicked() +{ + save(); + + if (!m_filesDialog) + { + std::vector fileNames = getFileNames(); + + m_filesDialog = std::make_shared( + "Select from Include Paths", + "The list contains all Include Paths found in the Compilation Database. Red paths do not exist. Select the " + "paths containing the header files you want to index with Coati."); + m_filesDialog->setup(); + + + utility::CompilationDatabase cdb(dynamic_cast(m_settings.get())->getCompilationDatabasePath().str()); + std::vector cdbHeaderPaths = cdb.getAllHeaderPaths(); + std::vector sourcePaths = m_settings->getSourcePaths(); + + cdbHeaderPaths = utility::unique(utility::concat(sourcePaths, cdbHeaderPaths)); + + dynamic_cast(m_filesDialog.get())->setPathsList(cdbHeaderPaths, sourcePaths); + + connect(m_filesDialog.get(), SIGNAL(finished()), this, SLOT(savedFilesDialog())); + connect(m_filesDialog.get(), SIGNAL(canceled()), this, SLOT(closedFilesDialog())); + } + + m_filesDialog->showWindow(); + m_filesDialog->raise(); +} + +void QtProjectWizzardContentPathsCDBHeader::savedFilesDialog() +{ + // TODO: extend instead of replace + m_list->setList(dynamic_cast(m_filesDialog.get())->getPathsList()); + + closedFilesDialog(); +} QtProjectWizzardContentPathsExclude::QtProjectWizzardContentPathsExclude( std::shared_ptr settings, QtProjectWizzardWindow* window diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.h b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.h index a646d120..279354c7 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.h +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.h @@ -1,13 +1,12 @@ #ifndef QT_PROJECT_WIZZARD_CONTENT_PATHS_H #define QT_PROJECT_WIZZARD_CONTENT_PATHS_H -#include -#include - #include "qt/window/project_wizzard/QtProjectWizzardContent.h" #include "utility/path_detector/CombinedPathDetector.h" class QtDirectoryListBox; +class QPushButton; +class QComboBox; class QtProjectWizzardContentPaths : public QtProjectWizzardContent @@ -72,8 +71,16 @@ public: class QtProjectWizzardContentPathsCDBHeader : public QtProjectWizzardContentPathsSource { + Q_OBJECT + public: QtProjectWizzardContentPathsCDBHeader(std::shared_ptr settings, QtProjectWizzardWindow* window); + + virtual void populate(QGridLayout* layout, int& row) override; + +private slots: + void buttonClicked(); + void savedFilesDialog(); }; diff --git a/src/lib_parser/CMakeLists.txt b/src/lib_parser/CMakeLists.txt index f39e7c3b..3fde1594 100644 --- a/src/lib_parser/CMakeLists.txt +++ b/src/lib_parser/CMakeLists.txt @@ -31,7 +31,7 @@ add_files( data/parser/cxx/PreprocessorCallbacks.h data/parser/cxx/utilityCxx.cpp data/parser/cxx/utilityCxx.h - + data/parser/java/JavaParser.cpp data/parser/java/JavaParser.h -) \ No newline at end of file +) diff --git a/src/trial/CMakeLists.txt b/src/trial/CMakeLists.txt index 4dabc897..90e16ddb 100644 --- a/src/trial/CMakeLists.txt +++ b/src/trial/CMakeLists.txt @@ -3,9 +3,11 @@ add_files( data/parser/cxx/TaskParseCxx.cpp data/parser/cxx/TaskParseWrapper.cpp - + data/parser/java/TaskParseJava.cpp + utility/CompilationDatabase.cpp + isTrial.cpp main.cpp ) diff --git a/src/trial/utility/CompilationDatabase.cpp b/src/trial/utility/CompilationDatabase.cpp new file mode 100644 index 00000000..9dcc4d95 --- /dev/null +++ b/src/trial/utility/CompilationDatabase.cpp @@ -0,0 +1,38 @@ +#include "utility/CompilationDatabase.h" + +#include +#include "utility/utility.h" + + +utility::CompilationDatabase::CompilationDatabase(std::string filename) + : m_filename(filename) +{ + getHeaders(); +} + +std::vector utility::CompilationDatabase::getAllHeaderPaths() +{ + std::vector paths = utility::concat(m_headers, m_systemHeaders); + paths = utility::concat(paths, m_frameworkHeaders); + paths = utility::unique(paths); + return paths; +} + +std::vector utility::CompilationDatabase::getHeaderPaths() +{ + return m_headers; +} + +std::vector utility::CompilationDatabase::getSystemHeaderPaths() +{ + return m_systemHeaders; +} + +std::vector utility::CompilationDatabase::getFrameworkHeaderPaths() +{ + return m_frameworkHeaders; +} + +void utility::CompilationDatabase::getHeaders() +{ +}