Commit 2860cb17 authored by Sergey Kalinichev's avatar Sergey Kalinichev

Moved a lot of the code into the KDevelop repository

Now the custom defines/includes plugin provides parser arguments.

Review 124139
parent e4b0d03f
......@@ -80,6 +80,7 @@ target_link_libraries(kdevclangsupport
kdevclangcodecompletion
kdevclangcodegen
kdevclangutil
sessionsettings
KF5::ThreadWeaver
KF5::TextEditor
......
......@@ -183,7 +183,7 @@ ClangParseJob::ClangParseJob(const IndexedString& url, ILanguageSupport* languag
} else {
m_environment.addIncludes(IDefinesAndIncludesManager::manager()->includes(tuUrl.str()));
m_environment.addDefines(IDefinesAndIncludesManager::manager()->defines(tuUrl.str()));
m_environment.setParserSettings(ClangSettingsManager::self()->defaultParserSettings());
m_environment.setParserSettings(ClangSettingsManager::self()->parserSettings(nullptr));
}
const bool isSource = ClangHelpers::isSource(tuUrl.str());
m_environment.setQuality(
......
......@@ -10,27 +10,23 @@ LINK_PUBLIC
KDev::Util
)
set(clangsettings_SRCS
clangconfigpage.cpp
clangsettingsplugin.cpp
configwidget.cpp
pathsmodel.cpp
sessionsettings/sessionsettings.cpp
set(sessionsettings_SRCS
sessionsettings/sessionsettings.cpp
)
ki18n_wrap_ui(clangsettings_SRCS
configwidget.ui
ki18n_wrap_ui(sessionsettings_SRCS
sessionsettings/sessionsettings.ui
)
kconfig_add_kcfg_files( clangsettings_SRCS clangprojectconfig.kcfgc sessionsettings/sessionconfig.kcfgc)
kconfig_add_kcfg_files(sessionsettings_SRCS sessionsettings/sessionconfig.kcfgc)
kdevplatform_add_plugin(kdevclangsettings JSON kdevclangsettings.json SOURCES ${clangsettings_SRCS})
add_library(sessionsettings
STATIC
${sessionsettings_SRCS}
)
target_link_libraries(kdevclangsettings
target_link_libraries(sessionsettings
LINK_PUBLIC
KDev::Project
KDev::Util
LINK_PRIVATE
settingsmanager
)
/*
* This file is part of KDevelop
*
* Copyright 2015 Sergey Kalinichev <kalinichev.so.0@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "clangconfigpage.h"
#include "configwidget.h"
#include <QVBoxLayout>
#include <QIcon>
ClangConfigPage::ClangConfigPage(KDevelop::IPlugin* plugin, const KDevelop::ProjectConfigOptions& options, QWidget* parent)
: ProjectConfigPage<ClangProjectConfig>(plugin, options, parent)
{
m_configWidget = new ConfigWidget(this, project());
auto layout = new QVBoxLayout(this);
layout->addWidget(m_configWidget);
connect(m_configWidget, &ConfigWidget::changed, this, &ClangConfigPage::changed);
}
ClangConfigPage::~ClangConfigPage()
{}
void ClangConfigPage::defaults()
{
ProjectConfigPage::defaults();
m_configWidget->defaults();
}
void ClangConfigPage::apply()
{
ProjectConfigPage::apply();
configWidget->writeSettings();
}
QString ClangConfigPage::name() const
{
return i18n("C/C++ parser");
}
QString ClangConfigPage::fullName() const
{
return i18n("Configure C/C++ parser");
}
QIcon ClangConfigPage::icon() const
{
return QIcon::fromTheme("kdevelop");
}
/*
* This file is part of KDevelop
*
* Copyright 2015 Sergey Kalinichev <kalinichev.so.0@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef KCM_CUSTOMBUILDSYSTEM_H
#define KCM_CUSTOMBUILDSYSTEM_H
#include <project/projectconfigpage.h>
#include "clangprojectconfig.h"
class ClangConfigPage : public ProjectConfigPage<ClangProjectConfig>
{
Q_OBJECT
public:
ClangConfigPage(KDevelop::IPlugin* plugin, const KDevelop::ProjectConfigOptions& options, QWidget* parent);
virtual ~ClangConfigPage();
virtual QString name() const override;
virtual QString fullName() const override;
virtual QIcon icon() const override;
virtual void apply() override;
virtual void defaults() override;
private:
class ConfigWidget* m_configWidget;
};
#endif
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd">
<kcfgfile arg="true"/>
</kcfg>
File=clangprojectconfig.kcfgc
ClassName=ClangProjectConfig
Singleton=true
Inherits=KDevelop::ProjectConfigSkeleton
IncludeFiles=project/projectconfigskeleton.h
......@@ -32,6 +32,7 @@
#include <interfaces/icore.h>
#include <interfaces/isession.h>
#include <interfaces/iproject.h>
#include <custom-definesandincludes/idefinesandincludesmanager.h>
#include <util/path.h>
#include <project/projectmodel.h>
......@@ -42,10 +43,6 @@ namespace
{
const QString settingsGroup = QStringLiteral("Clang Settings");
const QString parserGroup = QStringLiteral("group");
const QString parserPath = QStringLiteral("path");
const QString parserOptions = QStringLiteral("options");
const QString macros = QStringLiteral("macros");
const QString forwardDeclare = QStringLiteral("forwardDeclare");
......@@ -69,34 +66,6 @@ CodeCompletionSettings readCodeCompletionSettings(KConfig* cfg)
return settings;
}
ParserSettings parserOptionsForItem(const QVector<ParserSettingsEntry>& paths, const Path itemPath, const Path rootDirectory)
{
Path closestPath;
ParserSettings settings;
// find parser options configured to a path closest to the requested item
for (const auto& entry : paths) {
auto settingsEntry = entry;
Path targetDirectory = rootDirectory;
targetDirectory.addPath(entry.path);
if (targetDirectory == itemPath){
return settingsEntry.settings;
}
if (targetDirectory.isParentOf(itemPath)) {
if(settings.parserOptions.isEmpty() || targetDirectory.segments().size() > closestPath.segments().size()){
settings = settingsEntry.settings;
closestPath = targetDirectory;
}
}
}
return settings.parserOptions.isEmpty() ? ClangSettingsManager::self()->defaultParserSettings() : settings;
}
}
ClangSettingsManager* ClangSettingsManager::self()
......@@ -121,67 +90,12 @@ ParserSettings ClangSettingsManager::parserSettings(KDevelop::ProjectBaseItem* i
{
Q_ASSERT(QThread::currentThread() == qApp->thread());
if (!item) {
return defaultParserSettings();
}
return parserOptionsForItem(readPaths(item->project()), item->path(), item->project()->path());
return {IDefinesAndIncludesManager::manager()->parserArguments(item)};
}
ClangSettingsManager::ClangSettingsManager()
{}
ParserSettings ClangSettingsManager::parserSettings(const QString& item, KDevelop::IProject* project) const
{
const Path itemPath(item);
const Path rootDirectory = project->path();
return parserOptionsForItem(readPaths(project), itemPath, rootDirectory);
}
QVector<ParserSettingsEntry> ClangSettingsManager::readPaths(KDevelop::IProject* project) const
{
auto cfg = project->projectConfiguration().data();
auto grp = cfg->group(settingsGroup);
QVector<ParserSettingsEntry> paths;
for (const auto& grpName : grp.groupList()) {
if (!grpName.startsWith(parserGroup)) {
continue;
}
KConfigGroup pathgrp = grp.group(grpName);
ParserSettingsEntry path;
path.path = pathgrp.readEntry(parserPath, "");
if(path.path.isEmpty()){
continue;
}
path.settings.parserOptions = pathgrp.readEntry(parserOptions, defaultParserSettings().parserOptions);
paths.append(path);
}
return paths;
}
void ClangSettingsManager::writePaths(KDevelop::IProject* project, const QVector<ParserSettingsEntry>& paths)
{
auto cfg = project->projectConfiguration().data();
auto grp = cfg->group(settingsGroup);
grp.deleteGroup();
int pathIndex = 0;
for (const auto& path : paths) {
auto pathgrp = grp.group(parserGroup + QString::number(pathIndex++));
pathgrp.writeEntry(parserPath, path.path);
pathgrp.writeEntry(parserOptions, path.settings.parserOptions);
}
}
ParserSettings ClangSettingsManager::defaultParserSettings() const
{
return {QStringLiteral("-fspell-checking -Wdocumentation -std=c++11 -Wall")};
}
bool ParserSettings::isCpp() const
{
return parserOptions.contains(QStringLiteral("-std=c++"));
......
......@@ -44,13 +44,6 @@ struct ParserSettings
};
Q_DECLARE_METATYPE(ParserSettings);
struct ParserSettingsEntry
{
ParserSettings settings;
QString path;
};
Q_DECLARE_TYPEINFO(ParserSettingsEntry, Q_MOVABLE_TYPE);
struct CodeCompletionSettings
{
bool macros = true;
......@@ -72,14 +65,6 @@ public:
ParserSettings parserSettings(KDevelop::ProjectBaseItem* item) const;
ParserSettings parserSettings(const QString& item, KDevelop::IProject* project) const;
ParserSettings defaultParserSettings() const;
QVector<ParserSettingsEntry> readPaths(KDevelop::IProject* project) const;
void writePaths(KDevelop::IProject* project, const QVector<ParserSettingsEntry>& paths);
private:
ClangSettingsManager();
};
......
/*
* This file is part of KDevelop
*
* Copyright 2015 Sergey Kalinichev <kalinichev.so.0@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "clangsettingsplugin.h"
#include "clangconfigpage.h"
#include "sessionsettings/sessionsettings.h"
#include <KPluginFactory>
K_PLUGIN_FACTORY_WITH_JSON(ClangSettingsPluginFactory, "kdevclangsettings.json", registerPlugin<ClangSettingsPlugin>(); )
using namespace KDevelop;
ClangSettingsPlugin::ClangSettingsPlugin(QObject *parent, const QVariantList&)
: IPlugin( "kdevclangsettings", parent )
{}
int ClangSettingsPlugin::perProjectConfigPages() const
{
return 1;
}
KDevelop::ConfigPage* ClangSettingsPlugin::perProjectConfigPage(int number, const KDevelop::ProjectConfigOptions& options, QWidget* parent)
{
return (number == 0) ? new ClangConfigPage(this, options, parent) : nullptr;
}
int ClangSettingsPlugin::configPages() const
{
return 1;
}
KDevelop::ConfigPage* ClangSettingsPlugin::configPage(int number, QWidget* parent)
{
return (number == 0) ? new SessionSettings(parent) : nullptr;
}
#include "clangsettingsplugin.moc"
/*
* This file is part of KDevelop
*
* Copyright 2015 Sergey Kalinichev <kalinichev.so.0@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef CONFIGPAGEPLUGIN_H
#define CONFIGPAGEPLUGIN_H
#include <interfaces/iplugin.h>
class ClangSettingsPlugin : public KDevelop::IPlugin
{
Q_OBJECT
public:
ClangSettingsPlugin(QObject *parent, const QVariantList &args);
int perProjectConfigPages() const override;
KDevelop::ConfigPage* perProjectConfigPage(int number, const KDevelop::ProjectConfigOptions& options, QWidget* parent) override;
KDevelop::ConfigPage* configPage(int number, QWidget *parent) override;
int configPages() const override;
};
#endif // CONFIGPAGEPLUGIN_H
/*
* This file is part of KDevelop
*
* Copyright 2015 Sergey Kalinichev <kalinichev.so.0@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "configwidget.h"
#include "ui_configwidget.h"
#include "pathsmodel.h"
#include <interfaces/iproject.h>
#include <util/path.h>
#include <QFileDialog>
QString languageStandard(const QString& arguments)
{
int idx = arguments.indexOf("-std=");
if(idx == -1){
return QStringLiteral("c++11");
}
idx += 5;
int end = arguments.indexOf(' ', idx) != -1 ? arguments.indexOf(' ', idx) : arguments.size();
return arguments.mid(idx, end - idx);
}
ConfigWidget::ConfigWidget(QWidget* parent, KDevelop::IProject* project)
: QWidget(parent)
, m_ui(new Ui::ConfigWidget())
, m_project(project)
{
const auto projectFolder = project->path().toLocalFile();
m_ui->setupUi(this);
m_model = new PathsModel(this);
m_model->setProjectPath(project->path());
m_ui->pathView->setModel(m_model);
auto paths = ClangSettingsManager::self()->readPaths(project);
if (paths.isEmpty()) {
paths.append({ClangSettingsManager::self()->parserSettings(projectFolder, project), QStringLiteral(".")});
}
m_model->setPaths(paths);
m_ui->pathView->setCurrentIndex(m_model->index(0));
connect(m_ui->pathView, &QListView::activated, this, &ConfigWidget::itemActivated);
connect(m_ui->parserOptions, &QLineEdit::textEdited, this, &ConfigWidget::textEdited);
connect(m_model,&PathsModel::changed, this, &ConfigWidget::changed);
connect(m_model,&PathsModel::rowsInserted, this, &ConfigWidget::itemActivated);
connect(m_model,&PathsModel::rowsRemoved, this, &ConfigWidget::itemActivated);
m_ui->parserOptions->setText(ClangSettingsManager::self()->parserSettings(projectFolder, m_project).parserOptions);
QAction* delDefAction = new QAction(i18n("Delete path"), this);
delDefAction->setShortcut(QKeySequence(Qt::Key_Delete));
delDefAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
delDefAction->setIcon(QIcon::fromTheme(QStringLiteral("list-remove")));
m_ui->pathView->addAction(delDefAction);
m_ui->pathView->setContextMenuPolicy(Qt::ActionsContextMenu);
connect(delDefAction, &QAction::triggered, this, &ConfigWidget::deletePath);
connect(m_ui->addPath, &QPushButton::clicked, this, &ConfigWidget::addPath);
connect(m_ui->removePath, &QPushButton::clicked, this, &ConfigWidget::deletePath);
m_ui->languageStandards->setCurrentText(languageStandard(m_ui->parserOptions->text()));
connect(m_ui->languageStandards, static_cast<void(QComboBox::*)(const QString&)>(&QComboBox::activated), this, &ConfigWidget::languageStandardChanged);
}
ConfigWidget::~ConfigWidget() = default;
void ConfigWidget::itemActivated()
{
const auto selection = m_ui->pathView->selectionModel()->currentIndex();
if(!selection.isValid()){
m_ui->parserOptions->clear();
return;
}
auto settings = m_model->data(selection, PathsModel::ParserOptionsRole).value<ParserSettings>();
m_ui->parserOptions->setText(settings.parserOptions);
m_ui->languageStandards->setCurrentText(languageStandard(m_ui->parserOptions->text()));
}
void ConfigWidget::writeSettings()
{
ClangSettingsManager::self()->writePaths(m_project, m_model->paths());
}
void ConfigWidget::deletePath()
{
const auto selection = m_ui->pathView->selectionModel()->currentIndex();
m_model->removeRow(selection.row());
}
void ConfigWidget::addPath()
{
QFileDialog dlg(this, "", m_project->path().toLocalFile());
dlg.setFileMode(QFileDialog::Directory);
dlg.setOption(QFileDialog::ReadOnly, true);
if(dlg.exec() == QDialog::Rejected){
return;
}
m_model->addPath(dlg.directoryUrl().toLocalFile());
m_ui->pathView->setCurrentIndex(m_model->index(m_model->rowCount() - 1));
}
void ConfigWidget::textEdited()
{
const auto parserOptions = m_ui->parserOptions->text();
const auto index = m_ui->pathView->selectionModel()->currentIndex();
m_model->setData(index, QVariant::fromValue(ParserSettings {parserOptions}), PathsModel::ParserOptionsRole);
m_ui->languageStandards->setCurrentText(languageStandard(m_ui->parserOptions->text()));
}
void ConfigWidget::languageStandardChanged(const QString& standard)
{
auto text = m_ui->parserOptions->text();
auto currentStandard = languageStandard(text);
m_ui->parserOptions->setText(text.replace(currentStandard, standard));
textEdited();
}
void ConfigWidget::defaults()
{
ParserSettingsEntry entry;
entry.path = QStringLiteral(".");
entry.settings = ClangSettingsManager::self()->defaultParserSettings();
m_model->setPaths({entry});
m_ui->parserOptions->setText(entry.settings.parserOptions);
m_ui->languageStandards->setCurrentText(languageStandard(m_ui->parserOptions->text()));
}
/*
* This file is part of KDevelop
*
* Copyright 2015 Sergey Kalinichev <kalinichev.so.0@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef CONFIGWIDGET_H
#define CONFIGWIDGET_H
#include <QWidget>
#include <QScopedPointer>