forked from qt-creator/qt-creator
Clang: Remove PchManager
...which is the last dependency to libclang from the plugin. Change-Id: I173ee7e9621912ec88706b4cf62db2b1dbcf7610 Reviewed-by: Marco Bubke <marco.bubke@theqtcompany.com> Reviewed-by: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
This commit is contained in:
@@ -34,7 +34,6 @@
|
||||
#include "clangeditordocumentprocessor.h"
|
||||
#include "clangmodelmanagersupport.h"
|
||||
#include "clangutils.h"
|
||||
#include "pchmanager.h"
|
||||
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <coreplugin/icore.h>
|
||||
@@ -335,10 +334,8 @@ void IpcCommunicator::initializeBackend()
|
||||
|
||||
static QStringList projectPartOptions(const CppTools::ProjectPart::Ptr &projectPart)
|
||||
{
|
||||
QStringList options = ClangCodeModel::Utils::createClangOptions(projectPart,
|
||||
const QStringList options = ClangCodeModel::Utils::createClangOptions(projectPart,
|
||||
CppTools::ProjectFile::Unclassified); // No language option
|
||||
if (PchInfo::Ptr pchInfo = PchManager::instance()->pchInfo(projectPart))
|
||||
options += ClangCodeModel::Utils::createPCHInclusionOptions(pchInfo->fileName());
|
||||
|
||||
return options;
|
||||
}
|
||||
|
@@ -1,16 +1,12 @@
|
||||
include(../../qtcreatorplugin.pri)
|
||||
include(../../shared/clang/clang_installation.pri)
|
||||
|
||||
LIBS += $$LLVM_LIBS
|
||||
INCLUDEPATH += $$LLVM_INCLUDEPATH
|
||||
DEFINES += CLANGCODEMODEL_LIBRARY
|
||||
|
||||
# The following defines are used to determine the clang include path for intrinsics.
|
||||
DEFINES += CLANG_VERSION=\\\"$${LLVM_VERSION}\\\"
|
||||
DEFINES += "\"CLANG_RESOURCE_DIR=\\\"$${LLVM_LIBDIR}/clang/$${LLVM_VERSION}/include\\\"\""
|
||||
|
||||
unix:QMAKE_LFLAGS += -Wl,-rpath,\'$$LLVM_LIBDIR\'
|
||||
|
||||
SOURCES += \
|
||||
activationsequencecontextprocessor.cpp \
|
||||
activationsequenceprocessor.cpp \
|
||||
@@ -36,12 +32,7 @@ SOURCES += \
|
||||
clangtextmark.cpp \
|
||||
clangutils.cpp \
|
||||
completionchunkstotextconverter.cpp \
|
||||
highlightingmarksreporter.cpp \
|
||||
pchinfo.cpp \
|
||||
pchmanager.cpp \
|
||||
raii/scopedclangoptions.cpp \
|
||||
unit.cpp \
|
||||
unsavedfiledata.cpp
|
||||
highlightingmarksreporter.cpp
|
||||
|
||||
HEADERS += \
|
||||
activationsequencecontextprocessor.h \
|
||||
@@ -70,12 +61,7 @@ HEADERS += \
|
||||
clangutils.h \
|
||||
completionchunkstotextconverter.h \
|
||||
constants.h \
|
||||
highlightingmarksreporter.h \
|
||||
pchinfo.h \
|
||||
pchmanager.h \
|
||||
raii/scopedclangoptions.h \
|
||||
unit.h \
|
||||
unsavedfiledata.h
|
||||
highlightingmarksreporter.h
|
||||
|
||||
FORMS += clangprojectsettingspropertiespage.ui
|
||||
|
||||
|
@@ -23,16 +23,10 @@ QtcPlugin {
|
||||
property string llvmConfig: Clang.llvmConfig(qbs, QtcFunctions, QtcProcessOutputReader)
|
||||
property string llvmIncludeDir: Clang.includeDir(llvmConfig, QtcProcessOutputReader)
|
||||
property string llvmLibDir: Clang.libDir(llvmConfig, QtcProcessOutputReader)
|
||||
property string llvmLibs: Clang.libraries(qbs.targetOS)
|
||||
property string llvmVersion: Clang.version(llvmConfig, QtcProcessOutputReader)
|
||||
|
||||
condition: llvmConfig && File.exists(llvmIncludeDir.concat("/clang-c/Index.h"))
|
||||
|
||||
cpp.includePaths: base.concat(llvmIncludeDir)
|
||||
cpp.libraryPaths: base.concat(llvmLibDir)
|
||||
cpp.rpaths: cpp.libraryPaths
|
||||
cpp.dynamicLibraries: base.concat(llvmLibs)
|
||||
|
||||
cpp.defines: {
|
||||
var defines = base;
|
||||
// The following defines are used to determine the clang include path for intrinsics.
|
||||
@@ -95,16 +89,6 @@ QtcPlugin {
|
||||
"constants.h",
|
||||
"highlightingmarksreporter.cpp",
|
||||
"highlightingmarksreporter.h",
|
||||
"pchinfo.cpp",
|
||||
"pchinfo.h",
|
||||
"pchmanager.cpp",
|
||||
"pchmanager.h",
|
||||
"raii/scopedclangoptions.cpp",
|
||||
"raii/scopedclangoptions.h",
|
||||
"unit.cpp",
|
||||
"unit.h",
|
||||
"unsavedfiledata.cpp",
|
||||
"unsavedfiledata.h",
|
||||
]
|
||||
|
||||
Group {
|
||||
|
@@ -32,7 +32,6 @@
|
||||
|
||||
#include "clangprojectsettingspropertiespage.h"
|
||||
#include "constants.h"
|
||||
#include "pchmanager.h"
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
# include "test/clangcodecompletion_test.h"
|
||||
@@ -46,8 +45,6 @@
|
||||
|
||||
#include <texteditor/textmark.h>
|
||||
|
||||
#include <clang-c/Index.h>
|
||||
|
||||
namespace ClangCodeModel {
|
||||
namespace Internal {
|
||||
|
||||
@@ -61,23 +58,6 @@ void initializeTextMarks()
|
||||
Utils::Theme::ClangCodeModel_Error_TextMarkColor);
|
||||
}
|
||||
|
||||
static bool clangInitialised = false;
|
||||
static QMutex initialisationMutex;
|
||||
|
||||
void initializeClang()
|
||||
{
|
||||
if (clangInitialised)
|
||||
return;
|
||||
|
||||
QMutexLocker locker(&initialisationMutex);
|
||||
if (clangInitialised)
|
||||
return;
|
||||
|
||||
clang_toggleCrashRecovery(1);
|
||||
clang_enableStackTraces();
|
||||
clangInitialised = true;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
bool ClangCodeModelPlugin::initialize(const QStringList &arguments, QString *errorMessage)
|
||||
@@ -92,19 +72,8 @@ bool ClangCodeModelPlugin::initialize(const QStringList &arguments, QString *err
|
||||
panelFactory->setSimpleCreateWidgetFunction<ClangProjectSettingsWidget>(QIcon());
|
||||
ProjectExplorer::ProjectPanelFactory::registerFactory(panelFactory);
|
||||
|
||||
// Initialize Clang
|
||||
ClangCodeModel::Internal::initializeClang();
|
||||
|
||||
// Set up PchManager
|
||||
PchManager *pchManager = new PchManager(this);
|
||||
ProjectExplorer::SessionManager *sessionManager = ProjectExplorer::SessionManager::instance();
|
||||
connect(sessionManager, &ProjectExplorer::SessionManager::aboutToRemoveProject,
|
||||
pchManager, &PchManager::onAboutToRemoveProject);
|
||||
auto cppModelManager = CppTools::CppModelManager::instance();
|
||||
connect(cppModelManager, &CppTools::CppModelManager::projectPartsUpdated,
|
||||
pchManager, &PchManager::onProjectPartsUpdated);
|
||||
|
||||
// Register ModelManagerSupportProvider
|
||||
auto cppModelManager = CppTools::CppModelManager::instance();
|
||||
cppModelManager->setClangModelManagerSupportProvider(&m_modelManagerSupportProvider);
|
||||
|
||||
initializeTextMarks();
|
||||
|
@@ -32,14 +32,10 @@
|
||||
|
||||
#include "clangutils.h"
|
||||
|
||||
#include <cpptools/cppmodelmanager.h>
|
||||
#include <cpptools/cpptoolsreuse.h>
|
||||
#include <cpptools/cppworkingcopy.h>
|
||||
|
||||
#include <texteditor/texteditor.h>
|
||||
|
||||
#include <cplusplus/Token.h>
|
||||
|
||||
namespace ClangCodeModel {
|
||||
namespace Internal {
|
||||
|
||||
@@ -50,18 +46,13 @@ ClangCompletionAssistInterface::ClangCompletionAssistInterface(
|
||||
const QString &fileName,
|
||||
TextEditor::AssistReason reason,
|
||||
const CppTools::ProjectPart::HeaderPaths &headerPaths,
|
||||
const PchInfo::Ptr &pchInfo,
|
||||
const CPlusPlus::LanguageFeatures &features)
|
||||
: AssistInterface(textEditorWidget->document(), position, fileName, reason)
|
||||
, m_ipcCommunicator(ipcCommunicator)
|
||||
, m_headerPaths(headerPaths)
|
||||
, m_savedPchPointer(pchInfo)
|
||||
, m_languageFeatures(features)
|
||||
, m_textEditorWidget(textEditorWidget)
|
||||
{
|
||||
m_unsavedFiles = Utils::createUnsavedFiles(
|
||||
CppTools::CppModelManager::instance()->workingCopy(),
|
||||
CppTools::modifiedFiles());
|
||||
}
|
||||
|
||||
bool ClangCompletionAssistInterface::objcEnabled() const
|
||||
@@ -94,11 +85,6 @@ IpcCommunicator &ClangCompletionAssistInterface::ipcCommunicator() const
|
||||
return m_ipcCommunicator;
|
||||
}
|
||||
|
||||
const Utils::UnsavedFiles &ClangCompletionAssistInterface::unsavedFiles() const
|
||||
{
|
||||
return m_unsavedFiles;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace ClangCodeModel
|
||||
|
||||
|
@@ -32,7 +32,6 @@
|
||||
#define CLANGCODEMODEL_INTERNAL_CLANGCOMPLETIONASSISTINTERFACE_H
|
||||
|
||||
#include "clangbackendipcintegration.h"
|
||||
#include "pchinfo.h"
|
||||
#include "clangutils.h"
|
||||
|
||||
#include <cpptools/cppcompletionassistprovider.h>
|
||||
@@ -51,11 +50,9 @@ public:
|
||||
const QString &fileName,
|
||||
TextEditor::AssistReason reason,
|
||||
const CppTools::ProjectPart::HeaderPaths &headerPaths,
|
||||
const PchInfo::Ptr &pchInfo,
|
||||
const CPlusPlus::LanguageFeatures &features);
|
||||
|
||||
IpcCommunicator &ipcCommunicator() const;
|
||||
const Utils::UnsavedFiles &unsavedFiles() const;
|
||||
bool objcEnabled() const;
|
||||
const CppTools::ProjectPart::HeaderPaths &headerPaths() const;
|
||||
CPlusPlus::LanguageFeatures languageFeatures() const;
|
||||
@@ -65,10 +62,8 @@ public:
|
||||
|
||||
private:
|
||||
IpcCommunicator &m_ipcCommunicator;
|
||||
Utils::UnsavedFiles m_unsavedFiles;
|
||||
QStringList m_options;
|
||||
CppTools::ProjectPart::HeaderPaths m_headerPaths;
|
||||
Internal::PchInfo::Ptr m_savedPchPointer;
|
||||
CPlusPlus::LanguageFeatures m_languageFeatures;
|
||||
const TextEditor::TextEditorWidget *m_textEditorWidget;
|
||||
};
|
||||
|
@@ -33,7 +33,6 @@
|
||||
#include "clangcompletionassistprocessor.h"
|
||||
#include "clangeditordocumentprocessor.h"
|
||||
#include "clangutils.h"
|
||||
#include "pchmanager.h"
|
||||
|
||||
#include <cplusplus/Token.h>
|
||||
#include <cpptools/cppcompletionassistprocessor.h>
|
||||
@@ -73,14 +72,12 @@ TextEditor::AssistInterface *ClangCompletionAssistProvider::createAssistInterfac
|
||||
{
|
||||
const CppTools::ProjectPart::Ptr projectPart = Utils::projectPartForFileBasedOnProcessor(filePath);
|
||||
if (projectPart) {
|
||||
const PchInfo::Ptr pchInfo = PchManager::instance()->pchInfo(projectPart);
|
||||
return new ClangCompletionAssistInterface(m_ipcCommunicator,
|
||||
textEditorWidget,
|
||||
position,
|
||||
filePath,
|
||||
reason,
|
||||
projectPart->headerPaths,
|
||||
pchInfo,
|
||||
projectPart->languageFeatures);
|
||||
}
|
||||
|
||||
|
@@ -35,7 +35,6 @@
|
||||
#include "clangmodelmanagersupport.h"
|
||||
#include "clangutils.h"
|
||||
#include "highlightingmarksreporter.h"
|
||||
#include "pchinfo.h"
|
||||
|
||||
#include <diagnosticcontainer.h>
|
||||
#include <sourcelocationcontainer.h>
|
||||
|
@@ -30,11 +30,6 @@
|
||||
|
||||
#include "clangprojectsettings.h"
|
||||
#include "clangprojectsettingspropertiespage.h"
|
||||
#include "pchmanager.h"
|
||||
|
||||
#include <QButtonGroup>
|
||||
#include <QCoreApplication>
|
||||
#include <QFileDialog>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace ClangCodeModel::Internal;
|
||||
@@ -43,88 +38,4 @@ ClangProjectSettingsWidget::ClangProjectSettingsWidget(Project *project)
|
||||
: m_project(project)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
|
||||
ClangProjectSettings *cps = PchManager::instance()->settingsForProject(project);
|
||||
Q_ASSERT(cps);
|
||||
|
||||
QButtonGroup *pchGroup = new QButtonGroup(this);
|
||||
pchGroup->addButton(m_ui.noneButton, ClangProjectSettings::PchUse_None);
|
||||
pchGroup->addButton(m_ui.exactButton, ClangProjectSettings::PchUse_BuildSystem_Exact);
|
||||
pchGroup->addButton(m_ui.fuzzyButton, ClangProjectSettings::PchUse_BuildSystem_Fuzzy);
|
||||
pchGroup->addButton(m_ui.customButton, ClangProjectSettings::PchUse_Custom);
|
||||
switch (cps->pchUsage()) {
|
||||
case ClangProjectSettings::PchUse_None:
|
||||
case ClangProjectSettings::PchUse_BuildSystem_Exact:
|
||||
case ClangProjectSettings::PchUse_BuildSystem_Fuzzy:
|
||||
case ClangProjectSettings::PchUse_Custom:
|
||||
pchGroup->button(cps->pchUsage())->setChecked(true);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
pchUsageChanged(cps->pchUsage());
|
||||
connect(pchGroup, SIGNAL(buttonClicked(int)),
|
||||
this, SLOT(pchUsageChanged(int)));
|
||||
|
||||
m_ui.customField->setText(cps->customPchFile());
|
||||
connect(m_ui.customField, SIGNAL(editingFinished()),
|
||||
this, SLOT(customPchFileChanged()));
|
||||
connect(m_ui.customButton, SIGNAL(clicked()),
|
||||
this, SLOT(customPchButtonClicked()));
|
||||
}
|
||||
|
||||
void ClangProjectSettingsWidget::pchUsageChanged(int id)
|
||||
{
|
||||
ClangProjectSettings *cps = PchManager::instance()->settingsForProject(m_project);
|
||||
Q_ASSERT(cps);
|
||||
cps->setPchUsage(static_cast<ClangProjectSettings::PchUsage>(id));
|
||||
|
||||
switch (id) {
|
||||
case ClangProjectSettings::PchUse_None:
|
||||
case ClangProjectSettings::PchUse_BuildSystem_Fuzzy:
|
||||
case ClangProjectSettings::PchUse_BuildSystem_Exact:
|
||||
m_ui.customField->setEnabled(false);
|
||||
m_ui.chooseButton->setEnabled(false);
|
||||
break;
|
||||
|
||||
case ClangProjectSettings::PchUse_Custom:
|
||||
m_ui.customField->setEnabled(true);
|
||||
m_ui.chooseButton->setEnabled(true);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ClangProjectSettingsWidget::customPchFileChanged()
|
||||
{
|
||||
ClangProjectSettings *cps = PchManager::instance()->settingsForProject(m_project);
|
||||
Q_ASSERT(cps);
|
||||
if (cps->pchUsage() != ClangProjectSettings::PchUse_Custom)
|
||||
return;
|
||||
QString fileName = m_ui.customField->text();
|
||||
if (!QFile(fileName).exists())
|
||||
return;
|
||||
|
||||
cps->setCustomPchFile(fileName);
|
||||
}
|
||||
|
||||
void ClangProjectSettingsWidget::customPchButtonClicked()
|
||||
{
|
||||
ClangProjectSettings *cps = PchManager::instance()->settingsForProject(m_project);
|
||||
Q_ASSERT(cps);
|
||||
|
||||
QFileDialog d(this);
|
||||
d.setNameFilters(QStringList() << tr("Header Files (*.h)")
|
||||
<< tr("All Files (*)"));
|
||||
d.setFileMode(QFileDialog::ExistingFile);
|
||||
d.setDirectory(m_project->projectDirectory().toString());
|
||||
if (!d.exec())
|
||||
return;
|
||||
const QStringList fileNames = d.selectedFiles();
|
||||
if (fileNames.isEmpty() || fileNames.first().isEmpty())
|
||||
return;
|
||||
|
||||
m_ui.customField->setText(fileNames.first());
|
||||
cps->setCustomPchFile(fileNames.first());
|
||||
}
|
||||
|
@@ -33,8 +33,6 @@
|
||||
|
||||
#include "ui_clangprojectsettingspropertiespage.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
namespace ProjectExplorer {
|
||||
class Project;
|
||||
}
|
||||
@@ -49,11 +47,6 @@ class ClangProjectSettingsWidget: public QWidget
|
||||
public:
|
||||
ClangProjectSettingsWidget(ProjectExplorer::Project *project);
|
||||
|
||||
protected slots:
|
||||
void pchUsageChanged(int id);
|
||||
void customPchFileChanged();
|
||||
void customPchButtonClicked();
|
||||
|
||||
private:
|
||||
Ui::ClangProjectSettingsPropertiesPage m_ui;
|
||||
ProjectExplorer::Project *m_project;
|
||||
|
@@ -2,6 +2,9 @@
|
||||
<ui version="4.0">
|
||||
<class>ClangCodeModel::Internal::ClangProjectSettingsPropertiesPage</class>
|
||||
<widget class="QWidget" name="ClangCodeModel::Internal::ClangProjectSettingsPropertiesPage">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
@@ -32,25 +32,18 @@
|
||||
|
||||
#include "clangeditordocumentprocessor.h"
|
||||
|
||||
#include <clang-c/Index.h>
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/idocument.h>
|
||||
|
||||
#include <cpptools/baseeditordocumentparser.h>
|
||||
#include <cpptools/cppprojects.h>
|
||||
#include <cpptools/cppworkingcopy.h>
|
||||
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QLoggingCategory>
|
||||
#include <QRegularExpression>
|
||||
#include <QSet>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
using namespace ClangCodeModel;
|
||||
using namespace ClangCodeModel::Internal;
|
||||
@@ -62,21 +55,6 @@ namespace Utils {
|
||||
|
||||
Q_LOGGING_CATEGORY(verboseRunLog, "qtc.clangcodemodel.verboserun")
|
||||
|
||||
UnsavedFiles createUnsavedFiles(const WorkingCopy &workingCopy,
|
||||
const ::Utils::FileNameList &modifiedFiles)
|
||||
{
|
||||
UnsavedFiles result;
|
||||
QHashIterator< ::Utils::FileName, QPair<QByteArray, unsigned> > wcIter = workingCopy.iterator();
|
||||
while (wcIter.hasNext()) {
|
||||
wcIter.next();
|
||||
const ::Utils::FileName &fileName = wcIter.key();
|
||||
if (modifiedFiles.contains(fileName) && QFile(fileName.toString()).exists())
|
||||
result.insert(fileName.toString(), wcIter.value().first);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates list of message-line arguments required for correct parsing
|
||||
* @param pPart Null if file isn't part of any project
|
||||
|
@@ -33,20 +33,15 @@
|
||||
|
||||
#include "clang_global.h"
|
||||
|
||||
#include <cpptools/cppmodelmanager.h>
|
||||
#include <cpptools/cppprojects.h>
|
||||
|
||||
#include <QLoggingCategory>
|
||||
|
||||
namespace ClangCodeModel {
|
||||
namespace Utils {
|
||||
|
||||
typedef QMap<QString, QByteArray> UnsavedFiles;
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(verboseRunLog)
|
||||
|
||||
UnsavedFiles createUnsavedFiles(const CppTools::WorkingCopy &workingCopy,
|
||||
const ::Utils::FileNameList &modifiedFiles);
|
||||
|
||||
QStringList createClangOptions(const CppTools::ProjectPart::Ptr &pPart,
|
||||
CppTools::ProjectFile::Kind fileKind);
|
||||
QStringList createClangOptions(const CppTools::ProjectPart::Ptr &pPart,
|
||||
|
@@ -1,63 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms and
|
||||
** conditions see http://www.qt.io/terms-conditions. For further information
|
||||
** use the contact form at http://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "pchinfo.h"
|
||||
|
||||
#include <QDir>
|
||||
|
||||
using namespace ClangCodeModel::Internal;
|
||||
|
||||
PchInfo::PchInfo()
|
||||
{
|
||||
}
|
||||
|
||||
PchInfo::~PchInfo()
|
||||
{
|
||||
}
|
||||
|
||||
PchInfo::Ptr PchInfo::createEmpty()
|
||||
{
|
||||
return Ptr(new PchInfo);
|
||||
}
|
||||
|
||||
PchInfo::Ptr PchInfo::createWithFileName(const QString &inputFileName,
|
||||
const QStringList &options,
|
||||
bool objcEnabled)
|
||||
{
|
||||
Ptr result(new PchInfo);
|
||||
result->m_inputFileName = inputFileName;
|
||||
result->m_options = options;
|
||||
result->m_objcEnabled = objcEnabled;
|
||||
|
||||
// The next 2 lines are just here to generate the file name....
|
||||
result->m_file.open();
|
||||
result->m_file.close();
|
||||
return result;
|
||||
}
|
@@ -1,81 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms and
|
||||
** conditions see http://www.qt.io/terms-conditions. For further information
|
||||
** use the contact form at http://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef PCHINFO_H
|
||||
#define PCHINFO_H
|
||||
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QSharedPointer>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
namespace ClangCodeModel {
|
||||
namespace Internal {
|
||||
|
||||
class PchInfo
|
||||
{
|
||||
PchInfo();
|
||||
|
||||
public:
|
||||
typedef QSharedPointer<PchInfo> Ptr;
|
||||
|
||||
public:
|
||||
~PchInfo();
|
||||
|
||||
static Ptr createEmpty();
|
||||
static Ptr createWithFileName(const QString &inputFileName,
|
||||
const QStringList &options, bool objcEnabled);
|
||||
|
||||
/// \return the (temporary) file name for the PCH file.
|
||||
QString fileName() const
|
||||
{ return m_file.fileName(); }
|
||||
|
||||
/// \return the input file for the PCH compilation.
|
||||
QString inputFileName() const
|
||||
{ return m_inputFileName; }
|
||||
|
||||
/// \return the options used to generate this PCH file.
|
||||
QStringList options() const
|
||||
{ return m_options; }
|
||||
|
||||
bool objcWasEnabled() const
|
||||
{ return m_objcEnabled; }
|
||||
|
||||
private:
|
||||
QString m_inputFileName;
|
||||
QStringList m_options;
|
||||
bool m_objcEnabled;
|
||||
QTemporaryFile m_file;
|
||||
};
|
||||
|
||||
} // Internal namespace
|
||||
} // ClangCodeModel namespace
|
||||
|
||||
#endif // PCHINFO_H
|
@@ -1,512 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms and
|
||||
** conditions see http://www.qt.io/terms-conditions. For further information
|
||||
** use the contact form at http://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "pchmanager.h"
|
||||
#include "unit.h"
|
||||
#include "clangutils.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/progressmanager/progressmanager.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/runextensions.h>
|
||||
|
||||
#include <QFile>
|
||||
|
||||
using namespace ClangCodeModel;
|
||||
using namespace ClangCodeModel::Internal;
|
||||
using namespace CPlusPlus;
|
||||
|
||||
namespace {
|
||||
|
||||
QString getQString(const CXString &cxString, bool disposeCXString = true)
|
||||
{
|
||||
QString s = QString::fromUtf8(clang_getCString(cxString));
|
||||
if (disposeCXString)
|
||||
clang_disposeString(cxString);
|
||||
return s;
|
||||
}
|
||||
|
||||
QStringList formattedDiagnostics(const Unit::Ptr &unit)
|
||||
{
|
||||
QStringList diags;
|
||||
if (!unit->isLoaded())
|
||||
return diags;
|
||||
|
||||
const unsigned count = unit->getNumDiagnostics();
|
||||
for (unsigned i = 0; i < count; ++i) {
|
||||
CXDiagnostic diag = unit->getDiagnostic(i);
|
||||
|
||||
unsigned opt = CXDiagnostic_DisplaySourceLocation
|
||||
| CXDiagnostic_DisplayColumn
|
||||
| CXDiagnostic_DisplaySourceRanges
|
||||
| CXDiagnostic_DisplayOption
|
||||
| CXDiagnostic_DisplayCategoryId
|
||||
| CXDiagnostic_DisplayCategoryName
|
||||
;
|
||||
diags << getQString(clang_formatDiagnostic(diag, opt));
|
||||
clang_disposeDiagnostic(diag);
|
||||
}
|
||||
|
||||
return diags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to create a PCH file from a header file.
|
||||
*
|
||||
* \returns a boolean indicating success (true) or failure (false), and a
|
||||
* list of diagnostic messages.
|
||||
*/
|
||||
QPair<bool, QStringList> precompile(const PchInfo::Ptr &pchInfo)
|
||||
{
|
||||
// qDebug() << "*** Precompiling" << pchInfo->inputFileName()
|
||||
// << "into" << pchInfo->fileName()
|
||||
// << "with options" << pchInfo->options();
|
||||
|
||||
bool ok = false;
|
||||
|
||||
Unit::Ptr unit = Unit::create(pchInfo->inputFileName());
|
||||
unit->setCompilationOptions(pchInfo->options());
|
||||
|
||||
unsigned parseOpts = CXTranslationUnit_ForSerialization
|
||||
| CXTranslationUnit_Incomplete;
|
||||
unit->setManagementOptions(parseOpts);
|
||||
|
||||
unit->parse();
|
||||
if (unit->isLoaded())
|
||||
ok = CXSaveError_None == unit->save(pchInfo->fileName());
|
||||
|
||||
return qMakePair(ok, formattedDiagnostics(unit));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
PchManager *PchManager::m_instance = 0;
|
||||
|
||||
PchManager::PchManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
Q_ASSERT(!m_instance);
|
||||
m_instance = this;
|
||||
|
||||
QObject *msgMgr = Core::MessageManager::instance();
|
||||
connect(this, SIGNAL(pchMessage(QString,Core::MessageManager::PrintToOutputPaneFlags)),
|
||||
msgMgr, SLOT(write(QString,Core::MessageManager::PrintToOutputPaneFlags)));
|
||||
|
||||
connect(&m_pchGenerationWatcher, SIGNAL(finished()),
|
||||
this, SLOT(updateActivePchFiles()));
|
||||
}
|
||||
|
||||
PchManager::~PchManager()
|
||||
{
|
||||
Q_ASSERT(m_instance);
|
||||
m_instance = 0;
|
||||
qDeleteAll(m_projectSettings.values());
|
||||
m_projectSettings.clear();
|
||||
}
|
||||
|
||||
PchManager *PchManager::instance()
|
||||
{
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
PchInfo::Ptr PchManager::pchInfo(const ProjectPart::Ptr &projectPart) const
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
|
||||
return m_activePchFiles[projectPart];
|
||||
}
|
||||
|
||||
ClangProjectSettings *PchManager::settingsForProject(ProjectExplorer::Project *project)
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
|
||||
ClangProjectSettings *cps = m_projectSettings.value(project);
|
||||
if (!cps) {
|
||||
cps = new ClangProjectSettings(project);
|
||||
m_projectSettings.insert(project, cps);
|
||||
cps->pullSettings();
|
||||
connect(cps, SIGNAL(pchSettingsChanged()),
|
||||
this, SLOT(clangProjectSettingsChanged()));
|
||||
}
|
||||
return cps;
|
||||
}
|
||||
|
||||
void PchManager::setPCHInfo(const QList<ProjectPart::Ptr> &projectParts,
|
||||
const PchInfo::Ptr &pchInfo,
|
||||
const QPair<bool, QStringList> &msgs)
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
|
||||
foreach (ProjectPart::Ptr pPart, projectParts)
|
||||
m_activePchFiles[pPart] = pchInfo;
|
||||
|
||||
if (pchInfo) {
|
||||
if (msgs.first) {
|
||||
if (!pchInfo->fileName().isEmpty())
|
||||
emit pchMessage(tr("Successfully generated PCH file \"%1\".").arg(
|
||||
pchInfo->fileName()), Core::MessageManager::Silent);
|
||||
} else {
|
||||
emit pchMessage(tr("Failed to generate PCH file \"%1\".").arg(
|
||||
pchInfo->fileName()), Core::MessageManager::Silent);
|
||||
}
|
||||
if (!msgs.second.isEmpty())
|
||||
emit pchMessage(msgs.second.join(QLatin1Char('\n')), Core::MessageManager::Flash);
|
||||
}
|
||||
}
|
||||
|
||||
void PchManager::clangProjectSettingsChanged()
|
||||
{
|
||||
ClangProjectSettings *cps = qobject_cast<ClangProjectSettings *>(sender());
|
||||
if (!cps)
|
||||
return;
|
||||
|
||||
onProjectPartsUpdated(cps->project());
|
||||
}
|
||||
|
||||
void PchManager::onAboutToRemoveProject(ProjectExplorer::Project *project)
|
||||
{
|
||||
Q_UNUSED(project);
|
||||
|
||||
// we cannot ask the ModelManager for the parts, because, depending on
|
||||
// the order of signal delivery, it might already have wiped any information
|
||||
// about the project.
|
||||
|
||||
updateActivePchFiles();
|
||||
}
|
||||
|
||||
void PchManager::onProjectPartsUpdated(ProjectExplorer::Project *project)
|
||||
{
|
||||
ClangProjectSettings *cps = settingsForProject(project);
|
||||
Q_ASSERT(cps);
|
||||
|
||||
CppTools::CppModelManager *mmi = CppTools::CppModelManager::instance();
|
||||
const QList<ProjectPart::Ptr> projectParts = mmi->projectInfo(
|
||||
cps->project()).projectParts();
|
||||
updatePchInfo(cps, projectParts);
|
||||
}
|
||||
|
||||
void PchManager::updatePchInfo(ClangProjectSettings *cps,
|
||||
const QList<ProjectPart::Ptr> &projectParts)
|
||||
{
|
||||
if (m_pchGenerationWatcher.isRunning()) {
|
||||
m_pchGenerationWatcher.waitForFinished();
|
||||
}
|
||||
|
||||
const QString customPchFile = cps->customPchFile();
|
||||
const ClangProjectSettings::PchUsage pchUsage = cps->pchUsage();
|
||||
|
||||
void (*updateFunction)(QFutureInterface<void> &future,
|
||||
const PchManager::UpdateParams params) = 0;
|
||||
QString message;
|
||||
if (pchUsage == ClangProjectSettings::PchUse_None
|
||||
|| (pchUsage == ClangProjectSettings::PchUse_Custom && customPchFile.isEmpty())) {
|
||||
updateFunction = &PchManager::doPchInfoUpdateNone;
|
||||
message = QLatin1String("updatePchInfo: switching to none");
|
||||
} else if (pchUsage == ClangProjectSettings::PchUse_BuildSystem_Fuzzy) {
|
||||
updateFunction = &PchManager::doPchInfoUpdateFuzzy;
|
||||
message = QLatin1String("updatePchInfo: switching to build system (fuzzy)");
|
||||
} else if (pchUsage == ClangProjectSettings::PchUse_BuildSystem_Exact) {
|
||||
updateFunction = &PchManager::doPchInfoUpdateExact;
|
||||
message = QLatin1String("updatePchInfo: switching to build system (exact)");
|
||||
} else if (pchUsage == ClangProjectSettings::PchUse_Custom) {
|
||||
updateFunction = &PchManager::doPchInfoUpdateCustom;
|
||||
message = QLatin1String("updatePchInfo: switching to custom") + customPchFile;
|
||||
}
|
||||
|
||||
QTC_ASSERT(updateFunction && !message.isEmpty(), return);
|
||||
|
||||
Core::MessageManager::write(message, Core::MessageManager::Silent);
|
||||
QFuture<void> future = QtConcurrent::run(updateFunction,
|
||||
UpdateParams(customPchFile, projectParts));
|
||||
m_pchGenerationWatcher.setFuture(future);
|
||||
Core::ProgressManager::addTask(future, tr("Precompiling"), "Key.Tmp.Precompiling");
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool hasObjCFiles(const CppTools::ProjectPart::Ptr &projectPart)
|
||||
{
|
||||
foreach (const CppTools::ProjectFile &file, projectPart->files) {
|
||||
switch (file.kind) {
|
||||
case CppTools::ProjectFile::ObjCHeader:
|
||||
case CppTools::ProjectFile::ObjCSource:
|
||||
case CppTools::ProjectFile::ObjCXXHeader:
|
||||
case CppTools::ProjectFile::ObjCXXSource:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hasCppFiles(const CppTools::ProjectPart::Ptr &projectPart)
|
||||
{
|
||||
foreach (const CppTools::ProjectFile &file, projectPart->files) {
|
||||
switch (file.kind) {
|
||||
case CppTools::ProjectFile::CudaSource:
|
||||
case CppTools::ProjectFile::CXXHeader:
|
||||
case CppTools::ProjectFile::CXXSource:
|
||||
case CppTools::ProjectFile::OpenCLSource:
|
||||
case CppTools::ProjectFile::ObjCXXHeader:
|
||||
case CppTools::ProjectFile::ObjCXXSource:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CppTools::ProjectFile::Kind getPrefixFileKind(bool hasObjectiveC, bool hasCPlusPlus)
|
||||
{
|
||||
if (hasObjectiveC && hasCPlusPlus)
|
||||
return CppTools::ProjectFile::ObjCXXHeader;
|
||||
else if (hasObjectiveC)
|
||||
return CppTools::ProjectFile::ObjCHeader;
|
||||
else if (hasCPlusPlus)
|
||||
return CppTools::ProjectFile::CXXHeader;
|
||||
return CppTools::ProjectFile::CHeader;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PchManager::doPchInfoUpdateNone(QFutureInterface<void> &future,
|
||||
const PchManager::UpdateParams params)
|
||||
{
|
||||
future.setProgressRange(0, 1);
|
||||
PchInfo::Ptr emptyPch = PchInfo::createEmpty();
|
||||
PchManager::instance()->setPCHInfo(params.projectParts, emptyPch,
|
||||
qMakePair(true, QStringList()));
|
||||
future.setProgressValue(1);
|
||||
}
|
||||
|
||||
void PchManager::doPchInfoUpdateFuzzy(QFutureInterface<void> &future,
|
||||
const PchManager::UpdateParams params)
|
||||
{
|
||||
typedef ProjectPart::HeaderPath HeaderPath;
|
||||
QHash<QString, QSet<HeaderPath>> headers;
|
||||
QHash<QString, QSet<QByteArray> > definesPerPCH;
|
||||
QHash<QString, bool> objc;
|
||||
QHash<QString, bool> cplusplus;
|
||||
QHash<QString, ProjectPart::QtVersion> qtVersions;
|
||||
QHash<QString, ProjectPart::LanguageVersion> languageVersions;
|
||||
QHash<QString, ProjectPart::LanguageExtensions> languageExtensionsMap;
|
||||
QHash<QString, QList<ProjectPart::Ptr> > inputToParts;
|
||||
foreach (const ProjectPart::Ptr &projectPart, params.projectParts) {
|
||||
if (projectPart->precompiledHeaders.isEmpty())
|
||||
continue;
|
||||
const QString &pch = projectPart->precompiledHeaders.first(); // TODO: support more than 1 PCH file.
|
||||
if (!QFile(pch).exists())
|
||||
continue;
|
||||
inputToParts[pch].append(projectPart);
|
||||
|
||||
headers[pch].unite(QSet<HeaderPath>::fromList(projectPart->headerPaths));
|
||||
languageVersions[pch] = std::max(languageVersions.value(pch, ProjectPart::C89),
|
||||
projectPart->languageVersion);
|
||||
languageExtensionsMap[pch] = languageExtensionsMap[pch] | projectPart->languageExtensions;
|
||||
|
||||
if (hasObjCFiles(projectPart))
|
||||
objc[pch] = true;
|
||||
if (hasCppFiles(projectPart))
|
||||
cplusplus[pch] = true;
|
||||
|
||||
QSet<QByteArray> projectDefines = QSet<QByteArray>::fromList(projectPart->toolchainDefines.split('\n'));
|
||||
QMutableSetIterator<QByteArray> iter(projectDefines);
|
||||
while (iter.hasNext()){
|
||||
QByteArray v = iter.next();
|
||||
if (v.startsWith("#define _") || v.isEmpty()) // TODO: see ProjectPart::createClangOptions
|
||||
iter.remove();
|
||||
}
|
||||
projectDefines.unite(QSet<QByteArray>::fromList(projectPart->projectDefines.split('\n')));
|
||||
|
||||
if (definesPerPCH.contains(pch)) {
|
||||
definesPerPCH[pch].intersect(projectDefines);
|
||||
} else {
|
||||
definesPerPCH[pch] = projectDefines;
|
||||
}
|
||||
|
||||
qtVersions[pch] = projectPart->qtVersion;
|
||||
}
|
||||
|
||||
future.setProgressRange(0, definesPerPCH.size() + 1);
|
||||
future.setProgressValue(0);
|
||||
|
||||
foreach (const QString &pch, inputToParts.keys()) {
|
||||
if (future.isCanceled())
|
||||
return;
|
||||
ProjectPart::Ptr projectPart(new ProjectPart);
|
||||
projectPart->qtVersion = qtVersions[pch];
|
||||
projectPart->languageVersion = languageVersions[pch];
|
||||
projectPart->languageExtensions = languageExtensionsMap[pch];
|
||||
projectPart->headerPaths = headers[pch].toList();
|
||||
projectPart->updateLanguageFeatures();
|
||||
|
||||
QList<QByteArray> defines = definesPerPCH[pch].toList();
|
||||
if (!defines.isEmpty()) {
|
||||
projectPart->projectDefines = defines[0];
|
||||
for (int i = 1; i < defines.size(); ++i) {
|
||||
projectPart->projectDefines += '\n';
|
||||
projectPart->projectDefines += defines[i];
|
||||
}
|
||||
}
|
||||
|
||||
CppTools::ProjectFile::Kind prefixFileKind =
|
||||
getPrefixFileKind(objc.value(pch, false), cplusplus.value(pch, false));
|
||||
|
||||
QStringList options = Utils::createClangOptions(projectPart, prefixFileKind);
|
||||
projectPart.clear();
|
||||
|
||||
PchManager *pchManager = PchManager::instance();
|
||||
PchInfo::Ptr pchInfo = pchManager->findMatchingPCH(pch, options, true);
|
||||
QPair<bool, QStringList> msgs = qMakePair(true, QStringList());
|
||||
if (pchInfo.isNull()) {
|
||||
|
||||
pchInfo = PchInfo::createWithFileName(pch, options, objc[pch]);
|
||||
msgs = precompile(pchInfo);
|
||||
}
|
||||
pchManager->setPCHInfo(inputToParts[pch], pchInfo, msgs);
|
||||
future.setProgressValue(future.progressValue() + 1);
|
||||
}
|
||||
|
||||
future.setProgressValue(future.progressValue() + 1);
|
||||
}
|
||||
|
||||
void PchManager::doPchInfoUpdateExact(QFutureInterface<void> &future,
|
||||
const PchManager::UpdateParams params)
|
||||
{
|
||||
future.setProgressRange(0, params.projectParts.size() + 1);
|
||||
future.setProgressValue(0);
|
||||
foreach (const ProjectPart::Ptr &projectPart, params.projectParts) {
|
||||
if (future.isCanceled())
|
||||
return;
|
||||
if (projectPart->precompiledHeaders.isEmpty())
|
||||
continue;
|
||||
const QString &pch = projectPart->precompiledHeaders.first(); // TODO: support more than 1 PCH file.
|
||||
if (!QFile(pch).exists())
|
||||
continue;
|
||||
|
||||
const bool hasObjC = hasObjCFiles(projectPart);
|
||||
QStringList options = Utils::createClangOptions(
|
||||
projectPart, getPrefixFileKind(hasObjC, hasCppFiles(projectPart)));
|
||||
|
||||
PchManager *pchManager = PchManager::instance();
|
||||
PchInfo::Ptr pchInfo = pchManager->findMatchingPCH(pch, options, false);
|
||||
QPair<bool, QStringList> msgs = qMakePair(true, QStringList());
|
||||
if (pchInfo.isNull()) {
|
||||
pchInfo = PchInfo::createWithFileName(pch, options, hasObjC);
|
||||
msgs = precompile(pchInfo);
|
||||
}
|
||||
pchManager->setPCHInfo(QList<ProjectPart::Ptr>() << projectPart,
|
||||
pchInfo, msgs);
|
||||
future.setProgressValue(future.progressValue() + 1);
|
||||
}
|
||||
|
||||
future.setProgressValue(future.progressValue() + 1);
|
||||
}
|
||||
|
||||
void PchManager::doPchInfoUpdateCustom(QFutureInterface<void> &future,
|
||||
const PchManager::UpdateParams params)
|
||||
{
|
||||
future.setProgressRange(0, 1);
|
||||
future.setProgressValue(0);
|
||||
|
||||
ProjectPart::HeaderPaths headers;
|
||||
bool objc = false;
|
||||
bool cplusplus = false;
|
||||
ProjectPart::Ptr united(new ProjectPart());
|
||||
united->languageVersion = ProjectPart::C89;
|
||||
foreach (const ProjectPart::Ptr &projectPart, params.projectParts) {
|
||||
headers += projectPart->headerPaths;
|
||||
united->languageVersion = std::max(united->languageVersion, projectPart->languageVersion);
|
||||
united->qtVersion = std::max(united->qtVersion, projectPart->qtVersion);
|
||||
objc |= hasObjCFiles(projectPart);
|
||||
cplusplus |= hasCppFiles(projectPart);
|
||||
}
|
||||
united->updateLanguageFeatures();
|
||||
united->headerPaths = headers;
|
||||
QStringList opts = Utils::createClangOptions(
|
||||
united, getPrefixFileKind(objc, cplusplus));
|
||||
united.clear();
|
||||
|
||||
PchManager *pchManager = PchManager::instance();
|
||||
PchInfo::Ptr pchInfo = pchManager->findMatchingPCH(params.customPchFile, opts, true);
|
||||
QPair<bool, QStringList> msgs = qMakePair(true, QStringList());;
|
||||
if (future.isCanceled())
|
||||
return;
|
||||
if (pchInfo.isNull()) {
|
||||
pchInfo = PchInfo::createWithFileName(params.customPchFile, opts, objc);
|
||||
msgs = precompile(pchInfo);
|
||||
}
|
||||
pchManager->setPCHInfo(params.projectParts, pchInfo, msgs);
|
||||
future.setProgressValue(1);
|
||||
}
|
||||
|
||||
PchInfo::Ptr PchManager::findMatchingPCH(const QString &inputFileName,
|
||||
const QStringList &options,
|
||||
bool fuzzyMatching) const
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
|
||||
if (fuzzyMatching) {
|
||||
QStringList opts = options;
|
||||
opts.sort();
|
||||
foreach (PchInfo::Ptr pchInfo, m_activePchFiles.values()) {
|
||||
if (pchInfo->inputFileName() != inputFileName)
|
||||
continue;
|
||||
QStringList pchOpts = pchInfo->options();
|
||||
pchOpts.sort();
|
||||
if (pchOpts == opts)
|
||||
return pchInfo;
|
||||
}
|
||||
} else {
|
||||
foreach (PchInfo::Ptr pchInfo, m_activePchFiles.values())
|
||||
if (pchInfo->inputFileName() == inputFileName
|
||||
&& pchInfo->options() == options)
|
||||
return pchInfo;
|
||||
}
|
||||
|
||||
return PchInfo::Ptr();
|
||||
}
|
||||
|
||||
void PchManager::updateActivePchFiles()
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
|
||||
QSet<ProjectPart::Ptr> activeParts;
|
||||
CppTools::CppModelManager *mmi = CppTools::CppModelManager::instance();
|
||||
foreach (const CppTools::ProjectInfo &pi, mmi->projectInfos())
|
||||
activeParts.unite(QSet<ProjectPart::Ptr>::fromList(pi.projectParts()));
|
||||
QList<ProjectPart::Ptr> partsWithPCHFiles = m_activePchFiles.keys();
|
||||
foreach (ProjectPart::Ptr pPart, partsWithPCHFiles)
|
||||
if (!activeParts.contains(pPart))
|
||||
m_activePchFiles.remove(pPart);
|
||||
}
|
@@ -1,109 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms and
|
||||
** conditions see http://www.qt.io/terms-conditions. For further information
|
||||
** use the contact form at http://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef PCHMANAGER_H
|
||||
#define PCHMANAGER_H
|
||||
|
||||
#include "clangprojectsettings.h"
|
||||
#include "pchinfo.h"
|
||||
|
||||
#include <cpptools/cppmodelmanager.h>
|
||||
#include <projectexplorer/project.h>
|
||||
#include <coreplugin/messagemanager.h>
|
||||
|
||||
#include <QFutureWatcher>
|
||||
#include <QHash>
|
||||
#include <QMutex>
|
||||
#include <QObject>
|
||||
|
||||
namespace ClangCodeModel {
|
||||
namespace Internal {
|
||||
|
||||
class PchManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
typedef CppTools::ProjectPart ProjectPart;
|
||||
|
||||
static PchManager *m_instance;
|
||||
|
||||
public:
|
||||
PchManager(QObject *parent = 0);
|
||||
virtual ~PchManager();
|
||||
|
||||
static PchManager *instance();
|
||||
|
||||
PchInfo::Ptr pchInfo(const ProjectPart::Ptr &projectPart) const;
|
||||
ClangProjectSettings *settingsForProject(ProjectExplorer::Project *project);
|
||||
|
||||
signals:
|
||||
void pchMessage(const QString &message, Core::MessageManager::PrintToOutputPaneFlags flags);
|
||||
|
||||
public slots:
|
||||
void clangProjectSettingsChanged();
|
||||
void onAboutToRemoveProject(ProjectExplorer::Project *project);
|
||||
void onProjectPartsUpdated(ProjectExplorer::Project *project);
|
||||
|
||||
private slots:
|
||||
void updateActivePchFiles();
|
||||
|
||||
private:
|
||||
struct UpdateParams {
|
||||
UpdateParams(const QString &customPchFile, const QList<ProjectPart::Ptr> &projectParts)
|
||||
: customPchFile(customPchFile) , projectParts(projectParts) {}
|
||||
const QString customPchFile;
|
||||
const QList<ProjectPart::Ptr> projectParts;
|
||||
};
|
||||
|
||||
void updatePchInfo(ClangProjectSettings *cps,
|
||||
const QList<ProjectPart::Ptr> &projectParts);
|
||||
|
||||
static void doPchInfoUpdateNone(QFutureInterface<void> &future, const UpdateParams params);
|
||||
static void doPchInfoUpdateFuzzy(QFutureInterface<void> &future, const UpdateParams params);
|
||||
static void doPchInfoUpdateExact(QFutureInterface<void> &future, const UpdateParams params);
|
||||
static void doPchInfoUpdateCustom(QFutureInterface<void> &future, const UpdateParams params);
|
||||
|
||||
void setPCHInfo(const QList<ProjectPart::Ptr> &projectParts,
|
||||
const PchInfo::Ptr &pchInfo,
|
||||
const QPair<bool, QStringList> &msgs);
|
||||
PchInfo::Ptr findMatchingPCH(const QString &inputFileName, const QStringList &options,
|
||||
bool fuzzyMatching) const;
|
||||
|
||||
private:
|
||||
mutable QMutex m_mutex;
|
||||
QHash<ProjectPart::Ptr, PchInfo::Ptr> m_activePchFiles;
|
||||
QHash<ProjectExplorer::Project *, ClangProjectSettings *> m_projectSettings;
|
||||
QFutureWatcher<void> m_pchGenerationWatcher;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace ClangCodeModel
|
||||
|
||||
#endif // PCHMANAGER_H
|
@@ -1,104 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms and
|
||||
** conditions see http://www.qt.io/terms-conditions. For further information
|
||||
** use the contact form at http://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "scopedclangoptions.h"
|
||||
|
||||
namespace ClangCodeModel {
|
||||
|
||||
/**
|
||||
* @class ClangCodeModel::ScopedClangOptions
|
||||
* @brief Converts QStringList to raw options, acceptable by clang-c parsing and indexing API
|
||||
*/
|
||||
|
||||
ScopedClangOptions::ScopedClangOptions(const QStringList &options)
|
||||
: m_size(options.size())
|
||||
, m_rawOptions(new const char*[options.size()])
|
||||
{
|
||||
for (int i = 0 ; i < m_size; ++i)
|
||||
m_rawOptions[i] = qstrdup(options[i].toUtf8());
|
||||
}
|
||||
|
||||
ScopedClangOptions::~ScopedClangOptions()
|
||||
{
|
||||
for (int i = 0; i < m_size; ++i)
|
||||
delete[] m_rawOptions[i];
|
||||
delete[] m_rawOptions;
|
||||
}
|
||||
|
||||
const char **ScopedClangOptions::data() const
|
||||
{
|
||||
return m_rawOptions;
|
||||
}
|
||||
|
||||
int ScopedClangOptions::size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class ClangCodeModel::SharedClangOptions
|
||||
* @brief Shared wrapper around \a {ClangCodeModel::ScopedClangOptions} ScopedClangOptions
|
||||
*/
|
||||
|
||||
SharedClangOptions::SharedClangOptions()
|
||||
: d(0)
|
||||
{
|
||||
}
|
||||
|
||||
SharedClangOptions::SharedClangOptions(const QStringList &options)
|
||||
: d(new ScopedClangOptions(options))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Replaces options with new options list
|
||||
*/
|
||||
void SharedClangOptions::reloadOptions(const QStringList &options)
|
||||
{
|
||||
d = QSharedPointer<ScopedClangOptions>(new ScopedClangOptions(options));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Pointer to clang raw options or NULL if uninitialized
|
||||
*/
|
||||
const char **SharedClangOptions::data() const
|
||||
{
|
||||
return d ? d->data() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Options count or 0 if uninitialized
|
||||
*/
|
||||
int SharedClangOptions::size() const
|
||||
{
|
||||
return d ? d->size() : 0;
|
||||
}
|
||||
|
||||
} // namespace ClangCodeModel
|
@@ -1,73 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms and
|
||||
** conditions see http://www.qt.io/terms-conditions. For further information
|
||||
** use the contact form at http://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CLANGCODEMODEL_SCOPEDCLANGOPTIONS_H
|
||||
#define CLANGCODEMODEL_SCOPEDCLANGOPTIONS_H
|
||||
|
||||
#include "../clang_global.h"
|
||||
#include <QStringList>
|
||||
#include <QSharedPointer>
|
||||
|
||||
namespace ClangCodeModel {
|
||||
|
||||
class CLANG_EXPORT ScopedClangOptions
|
||||
{
|
||||
public:
|
||||
ScopedClangOptions(const QStringList &options);
|
||||
~ScopedClangOptions();
|
||||
|
||||
const char **data() const;
|
||||
int size() const;
|
||||
|
||||
private:
|
||||
void release();
|
||||
|
||||
int m_size;
|
||||
const char **m_rawOptions;
|
||||
};
|
||||
|
||||
class CLANG_EXPORT SharedClangOptions
|
||||
{
|
||||
public:
|
||||
SharedClangOptions();
|
||||
SharedClangOptions(const QStringList &options);
|
||||
|
||||
void reloadOptions(const QStringList &options);
|
||||
|
||||
const char **data() const;
|
||||
int size() const;
|
||||
|
||||
private:
|
||||
QSharedPointer<ScopedClangOptions> d;
|
||||
};
|
||||
|
||||
} // namespace ClangCodeModel
|
||||
|
||||
#endif // CLANGCODEMODEL_SCOPEDCLANGOPTIONS_H
|
@@ -1,335 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms and
|
||||
** conditions see http://www.qt.io/terms-conditions. For further information
|
||||
** use the contact form at http://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "unit.h"
|
||||
|
||||
#include "clangutils.h"
|
||||
#include "unsavedfiledata.h"
|
||||
|
||||
#include <clang-c/Index.h>
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QVector>
|
||||
#include <QtCore/QSharedData>
|
||||
|
||||
#ifdef DEBUG_UNIT_COUNT
|
||||
# include <QAtomicInt>
|
||||
# include <QDebug>
|
||||
static QBasicAtomicInt unitDataCount = Q_BASIC_ATOMIC_INITIALIZER(0);
|
||||
#endif // DEBUG_UNIT_COUNT
|
||||
|
||||
using namespace ClangCodeModel;
|
||||
using namespace ClangCodeModel::Internal;
|
||||
|
||||
Unit::Unit()
|
||||
: m_index(0)
|
||||
, m_tu(0)
|
||||
, m_managementOptions(0)
|
||||
{}
|
||||
|
||||
Unit::Unit(const QString &fileName)
|
||||
: m_index(clang_createIndex(/*excludeDeclsFromPCH*/ 1, Utils::verboseRunLog().isDebugEnabled()))
|
||||
, m_tu(0)
|
||||
, m_fileName(fileName.toUtf8())
|
||||
, m_managementOptions(0)
|
||||
{}
|
||||
|
||||
Unit::~Unit()
|
||||
{
|
||||
unload();
|
||||
clang_disposeIndex(m_index);
|
||||
m_index = 0;
|
||||
}
|
||||
|
||||
Unit::Ptr Unit::create()
|
||||
{
|
||||
return Unit::Ptr(new Unit);
|
||||
}
|
||||
|
||||
Unit::Ptr Unit::create(const QString &fileName)
|
||||
{
|
||||
return Unit::Ptr(new Unit(fileName));
|
||||
}
|
||||
|
||||
const QString Unit::fileName() const
|
||||
{
|
||||
return QString::fromUtf8(m_fileName.data(), m_fileName.size());
|
||||
}
|
||||
|
||||
bool Unit::isLoaded() const
|
||||
{
|
||||
return m_tu && m_index;
|
||||
}
|
||||
|
||||
const QDateTime &Unit::timeStamp() const
|
||||
{
|
||||
return m_timeStamp;
|
||||
}
|
||||
|
||||
QStringList Unit::compilationOptions() const
|
||||
{
|
||||
return m_compOptions;
|
||||
}
|
||||
|
||||
void Unit::setCompilationOptions(const QStringList &compOptions)
|
||||
{
|
||||
m_compOptions = compOptions;
|
||||
m_sharedCompOptions.reloadOptions(compOptions);
|
||||
}
|
||||
|
||||
ClangCodeModel::Utils::UnsavedFiles Unit::unsavedFiles() const
|
||||
{
|
||||
return m_unsaved;
|
||||
}
|
||||
|
||||
void Unit::setUnsavedFiles(const ClangCodeModel::Utils::UnsavedFiles &unsavedFiles)
|
||||
{
|
||||
m_unsaved = unsavedFiles;
|
||||
}
|
||||
|
||||
unsigned Unit::managementOptions() const
|
||||
{
|
||||
return m_managementOptions;
|
||||
}
|
||||
|
||||
void Unit::setManagementOptions(unsigned managementOptions)
|
||||
{
|
||||
m_managementOptions = managementOptions;
|
||||
}
|
||||
|
||||
void Unit::parse()
|
||||
{
|
||||
unload();
|
||||
|
||||
updateTimeStamp();
|
||||
|
||||
UnsavedFileData unsaved(m_unsaved);
|
||||
m_tu = clang_parseTranslationUnit(m_index, m_fileName.constData(),
|
||||
m_sharedCompOptions.data(), m_sharedCompOptions.size(),
|
||||
unsaved.files(), unsaved.count(),
|
||||
m_managementOptions);
|
||||
}
|
||||
|
||||
void Unit::reparse()
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
UnsavedFileData unsaved(m_unsaved);
|
||||
const unsigned opts = clang_defaultReparseOptions(m_tu);
|
||||
if (clang_reparseTranslationUnit(m_tu, unsaved.count(), unsaved.files(), opts) != 0)
|
||||
unload();
|
||||
}
|
||||
|
||||
int Unit::save(const QString &unitFileName)
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return clang_saveTranslationUnit(m_tu, unitFileName.toUtf8().constData(),
|
||||
clang_defaultSaveOptions(m_tu));
|
||||
}
|
||||
|
||||
void Unit::unload()
|
||||
{
|
||||
if (m_tu) {
|
||||
clang_disposeTranslationUnit(m_tu);
|
||||
m_tu = 0;
|
||||
|
||||
#ifdef DEBUG_UNIT_COUNT
|
||||
qDebug() << "# translation units:" << (unitDataCount.fetchAndAddOrdered(-1) - 1);
|
||||
#endif // DEBUG_UNIT_COUNT
|
||||
}
|
||||
}
|
||||
|
||||
CXFile Unit::getFile() const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return clang_getFile(m_tu, m_fileName.constData());
|
||||
}
|
||||
|
||||
CXCursor Unit::getCursor(const CXSourceLocation &location) const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return clang_getCursor(m_tu, location);
|
||||
}
|
||||
|
||||
CXSourceLocation Unit::getLocation(const CXFile &file, unsigned line, unsigned column) const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return clang_getLocation(m_tu, file, line, column);
|
||||
}
|
||||
|
||||
void Unit::tokenize(CXSourceRange range, CXToken **tokens, unsigned *tokenCount) const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
Q_ASSERT(tokens);
|
||||
Q_ASSERT(tokenCount);
|
||||
Q_ASSERT(!clang_Range_isNull(range));
|
||||
|
||||
clang_tokenize(m_tu, range, tokens, tokenCount);
|
||||
}
|
||||
|
||||
void Unit::disposeTokens(CXToken *tokens, unsigned tokenCount) const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
clang_disposeTokens(m_tu, tokens, tokenCount);
|
||||
}
|
||||
|
||||
CXSourceRange Unit::getTokenExtent(const CXToken &token) const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return clang_getTokenExtent(m_tu, token);
|
||||
}
|
||||
|
||||
void Unit::annotateTokens(CXToken *tokens, unsigned tokenCount, CXCursor *cursors) const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
Q_ASSERT(tokens);
|
||||
Q_ASSERT(cursors);
|
||||
|
||||
clang_annotateTokens(m_tu, tokens, tokenCount, cursors);
|
||||
}
|
||||
|
||||
CXTranslationUnit Unit::clangTranslationUnit() const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return m_tu;
|
||||
}
|
||||
|
||||
CXIndex Unit::clangIndex() const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return m_index;
|
||||
}
|
||||
|
||||
CXCursor Unit::getTranslationUnitCursor() const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return clang_getTranslationUnitCursor(m_tu);
|
||||
}
|
||||
|
||||
CXString Unit::getTranslationUnitSpelling() const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return clang_getTranslationUnitSpelling(m_tu);
|
||||
}
|
||||
|
||||
void Unit::getInclusions(CXInclusionVisitor visitor, CXClientData clientData) const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
clang_getInclusions(m_tu, visitor, clientData);
|
||||
}
|
||||
|
||||
unsigned Unit::getNumDiagnostics() const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return clang_getNumDiagnostics(m_tu);
|
||||
}
|
||||
|
||||
CXDiagnostic Unit::getDiagnostic(unsigned index) const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return clang_getDiagnostic(m_tu, index);
|
||||
}
|
||||
|
||||
void Unit::updateTimeStamp()
|
||||
{
|
||||
m_timeStamp = QDateTime::currentDateTime();
|
||||
}
|
||||
|
||||
IdentifierTokens::IdentifierTokens(const Unit &unit, unsigned firstLine, unsigned lastLine)
|
||||
: m_unit(unit)
|
||||
, m_tokenCount(0)
|
||||
, m_tokens(0)
|
||||
, m_cursors(0)
|
||||
, m_extents(0)
|
||||
{
|
||||
Q_ASSERT(unit.isLoaded());
|
||||
|
||||
// Calculate the range:
|
||||
CXFile file = unit.getFile();
|
||||
CXSourceLocation startLocation = unit.getLocation(file, firstLine, 1);
|
||||
CXSourceLocation endLocation = unit.getLocation(file, lastLine, 1);
|
||||
CXSourceRange range = clang_getRange(startLocation, endLocation);
|
||||
|
||||
// Retrieve all identifier tokens:
|
||||
unit.tokenize(range, &m_tokens, &m_tokenCount);
|
||||
if (m_tokenCount == 0)
|
||||
return;
|
||||
|
||||
// Get the cursors for the tokens:
|
||||
m_cursors = new CXCursor[m_tokenCount];
|
||||
unit.annotateTokens(m_tokens,
|
||||
m_tokenCount,
|
||||
m_cursors);
|
||||
|
||||
m_extents = new CXSourceRange[m_tokenCount];
|
||||
// Create the markers using the cursor to check the types:
|
||||
for (unsigned i = 0; i < m_tokenCount; ++i)
|
||||
m_extents[i] = unit.getTokenExtent(m_tokens[i]);
|
||||
}
|
||||
|
||||
IdentifierTokens::~IdentifierTokens()
|
||||
{
|
||||
dispose();
|
||||
}
|
||||
|
||||
void IdentifierTokens::dispose()
|
||||
{
|
||||
if (!m_unit.isLoaded())
|
||||
return;
|
||||
|
||||
if (m_tokenCount && m_tokens) {
|
||||
m_unit.disposeTokens(m_tokens, m_tokenCount);
|
||||
m_tokens = 0;
|
||||
m_tokenCount = 0;
|
||||
}
|
||||
|
||||
if (m_cursors) {
|
||||
delete[] m_cursors;
|
||||
m_cursors = 0;
|
||||
}
|
||||
|
||||
if (m_extents) {
|
||||
delete[] m_extents;
|
||||
m_extents = 0;
|
||||
}
|
||||
}
|
@@ -1,197 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms and
|
||||
** conditions see http://www.qt.io/terms-conditions. For further information
|
||||
** use the contact form at http://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef UNIT_H
|
||||
#define UNIT_H
|
||||
|
||||
#include "clangutils.h"
|
||||
#include "raii/scopedclangoptions.h"
|
||||
|
||||
#include <clang-c/Index.h>
|
||||
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QSharedPointer>
|
||||
#include <QMetaType>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QVarLengthArray>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QDateTime;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace ClangCodeModel {
|
||||
namespace Internal {
|
||||
|
||||
class UnitData;
|
||||
|
||||
/*
|
||||
* This is a minimal wrapper around clang's translation unit functionality.
|
||||
* It should should contain only the very basic primitives which allow other
|
||||
* components such as code completion, code navigation, and others to access
|
||||
* data which directly depends on the translation unit.
|
||||
*
|
||||
* In other words, what's wrapped here is only the functions that receive a
|
||||
* CXTranslationUnit as a parameter. And this class itself is then the corresponding
|
||||
* abstraction of the CXTranslationUnit.
|
||||
*
|
||||
* Notes:
|
||||
* - This class is not thread-safe.
|
||||
* - It's responsibility of the client to make sure that the wrapped translation
|
||||
* unit is consistent with the other data such as cursor and locations being used.
|
||||
*
|
||||
* @TODO: This is similar but not exactly the same as the current ClangWrapper class.
|
||||
* That class is now tuned to specific features, so it's not generic enough to be used
|
||||
* an underlying component and aslo don't provide the data in a fine granularity as
|
||||
* needed here. At some point we should split ClangWrapper into its different logical
|
||||
* components and use this is the underlying structure.
|
||||
*/
|
||||
class Unit
|
||||
{
|
||||
Q_DISABLE_COPY(Unit)
|
||||
|
||||
Unit();
|
||||
explicit Unit(const QString &fileName);
|
||||
|
||||
public:
|
||||
~Unit();
|
||||
|
||||
typedef QSharedPointer<Unit> Ptr;
|
||||
static Ptr create();
|
||||
static Ptr create(const QString &fileName);
|
||||
|
||||
bool isLoaded() const;
|
||||
|
||||
const QString fileName() const;
|
||||
|
||||
const QDateTime &timeStamp() const;
|
||||
|
||||
QStringList compilationOptions() const;
|
||||
void setCompilationOptions(const QStringList &compOptions);
|
||||
|
||||
Utils::UnsavedFiles unsavedFiles() const;
|
||||
void setUnsavedFiles(const ClangCodeModel::Utils::UnsavedFiles &unsavedFiles);
|
||||
|
||||
unsigned managementOptions() const;
|
||||
void setManagementOptions(unsigned managementOptions);
|
||||
|
||||
// Methods for generating the TU. Name mappings are direct, for example:
|
||||
// - parse corresponds to clang_parseTranslationUnit
|
||||
// - createFromSourceFile corresponds to clang_createTranslationUnitFromSourceFile
|
||||
void parse();
|
||||
void reparse();
|
||||
int save(const QString &unitFileName);
|
||||
void unload();
|
||||
|
||||
// Simple forwarding methods, separated by clang categories for convenience.
|
||||
// As above, the names are directly mapped. Separated by categories as clang for convenience.
|
||||
// Note that only methods that take the TU as a parameter should be wrapped.
|
||||
|
||||
// - Diagnostic reporting
|
||||
unsigned getNumDiagnostics() const;
|
||||
CXDiagnostic getDiagnostic(unsigned index) const;
|
||||
|
||||
// - Translation unit manipulation
|
||||
CXString getTranslationUnitSpelling() const;
|
||||
|
||||
// - File manipulation routines
|
||||
CXFile getFile() const;
|
||||
|
||||
// - Mapping between cursors and source code
|
||||
CXCursor getCursor(const CXSourceLocation &location) const;
|
||||
|
||||
// - Miscellaneous utility functions
|
||||
void getInclusions(CXInclusionVisitor visitor, CXClientData clientData) const;
|
||||
|
||||
// - Cursor manipulations
|
||||
CXCursor getTranslationUnitCursor() const;
|
||||
|
||||
// - Physical source locations
|
||||
CXSourceLocation getLocation(const CXFile &file, unsigned line, unsigned column) const;
|
||||
|
||||
void tokenize(CXSourceRange range, CXToken **tokens, unsigned *tokenCount) const;
|
||||
void disposeTokens(CXToken *tokens, unsigned tokenCount) const;
|
||||
CXSourceRange getTokenExtent(const CXToken &token) const;
|
||||
void annotateTokens(CXToken *tokens, unsigned tokenCount, CXCursor *cursors) const;
|
||||
|
||||
CXTranslationUnit clangTranslationUnit() const;
|
||||
CXIndex clangIndex() const;
|
||||
|
||||
private:
|
||||
void updateTimeStamp();
|
||||
|
||||
CXIndex m_index;
|
||||
CXTranslationUnit m_tu;
|
||||
QByteArray m_fileName;
|
||||
QStringList m_compOptions;
|
||||
SharedClangOptions m_sharedCompOptions;
|
||||
unsigned m_managementOptions;
|
||||
Utils::UnsavedFiles m_unsaved;
|
||||
QDateTime m_timeStamp;
|
||||
};
|
||||
|
||||
class IdentifierTokens
|
||||
{
|
||||
Q_DISABLE_COPY(IdentifierTokens)
|
||||
|
||||
public:
|
||||
IdentifierTokens(const Unit &m_unit, unsigned firstLine, unsigned lastLine);
|
||||
~IdentifierTokens();
|
||||
|
||||
unsigned count() const
|
||||
{ return m_tokenCount; }
|
||||
|
||||
const CXToken &token(unsigned nr) const
|
||||
{ Q_ASSERT(nr < count()); return m_tokens[nr]; }
|
||||
|
||||
const CXCursor &cursor(unsigned nr) const
|
||||
{ Q_ASSERT(nr < count()); return m_cursors[nr]; }
|
||||
|
||||
const CXSourceRange &extent(unsigned nr) const
|
||||
{ Q_ASSERT(nr < count()); return m_extents[nr]; }
|
||||
|
||||
private:
|
||||
void dispose();
|
||||
|
||||
private:
|
||||
const Unit &m_unit;
|
||||
unsigned m_tokenCount;
|
||||
CXToken *m_tokens;
|
||||
|
||||
CXCursor *m_cursors;
|
||||
CXSourceRange *m_extents;
|
||||
};
|
||||
|
||||
} // Internal
|
||||
} // Clang
|
||||
|
||||
Q_DECLARE_METATYPE(ClangCodeModel::Internal::Unit::Ptr)
|
||||
|
||||
#endif // UNIT_H
|
@@ -1,62 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms and
|
||||
** conditions see http://www.qt.io/terms-conditions. For further information
|
||||
** use the contact form at http://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "unsavedfiledata.h"
|
||||
|
||||
using namespace ClangCodeModel::Internal;
|
||||
|
||||
UnsavedFileData::UnsavedFileData(const UnsavedFiles &unsavedFiles)
|
||||
: m_count(unsavedFiles.count())
|
||||
, m_files(0)
|
||||
{
|
||||
if (m_count) {
|
||||
m_files = new CXUnsavedFile[m_count];
|
||||
unsigned idx = 0;
|
||||
for (UnsavedFiles::const_iterator it = unsavedFiles.begin(); it != unsavedFiles.end(); ++it, ++idx) {
|
||||
QByteArray contents = it.value();
|
||||
const char *contentChars = qstrdup(contents.constData());
|
||||
m_files[idx].Contents = contentChars;
|
||||
m_files[idx].Length = contents.size();
|
||||
|
||||
const char *fileName = qstrdup(it.key().toUtf8().constData());
|
||||
m_files[idx].Filename = fileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnsavedFileData::~UnsavedFileData()
|
||||
{
|
||||
for (unsigned i = 0; i < m_count; ++i) {
|
||||
delete[] m_files[i].Contents;
|
||||
delete[] m_files[i].Filename;
|
||||
}
|
||||
|
||||
delete[] m_files;
|
||||
}
|
@@ -1,66 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms and
|
||||
** conditions see http://www.qt.io/terms-conditions. For further information
|
||||
** use the contact form at http://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CLANG_INTERNAL_UNSAVEDFILEDATA_H
|
||||
#define CLANG_INTERNAL_UNSAVEDFILEDATA_H
|
||||
|
||||
#include "clangutils.h"
|
||||
|
||||
#include <clang-c/Index.h>
|
||||
|
||||
namespace ClangCodeModel {
|
||||
namespace Internal {
|
||||
|
||||
class UnsavedFileData
|
||||
{
|
||||
UnsavedFileData(const UnsavedFileData &);
|
||||
UnsavedFileData &operator=(const UnsavedFileData &);
|
||||
|
||||
typedef ClangCodeModel::Utils::UnsavedFiles UnsavedFiles;
|
||||
|
||||
public:
|
||||
UnsavedFileData(const UnsavedFiles &unsavedFiles);
|
||||
~UnsavedFileData();
|
||||
|
||||
unsigned count() const
|
||||
{ return m_count; }
|
||||
|
||||
CXUnsavedFile *files() const
|
||||
{ return m_files; }
|
||||
|
||||
private:
|
||||
unsigned m_count;
|
||||
CXUnsavedFile *m_files;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace ClangCodeModel
|
||||
|
||||
#endif // CLANG_INTERNAL_UNSAVEDFILEDATA_H
|
Reference in New Issue
Block a user