forked from qt-creator/qt-creator
Clang: clean up unit handling.
- Use a QSharedPointer instead of an explicitly shared pointer. - Remove the LiveUnitManager. Change-Id: I05bf32c1f77c17f42ee1da39f1353cff580fa6eb Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
This commit is contained in:
committed by
Nikolai Kosjar
parent
2251958375
commit
a4b6e35ac4
@@ -35,7 +35,6 @@ SOURCES += \
|
||||
$$PWD/unit.cpp \
|
||||
$$PWD/utils.cpp \
|
||||
$$PWD/utils_p.cpp \
|
||||
$$PWD/liveunitsmanager.cpp \
|
||||
$$PWD/semanticmarker.cpp \
|
||||
$$PWD/diagnostic.cpp \
|
||||
$$PWD/unsavedfiledata.cpp \
|
||||
@@ -58,7 +57,6 @@ HEADERS += \
|
||||
$$PWD/unit.h \
|
||||
$$PWD/utils.h \
|
||||
$$PWD/utils_p.h \
|
||||
$$PWD/liveunitsmanager.h \
|
||||
$$PWD/semanticmarker.h \
|
||||
$$PWD/diagnostic.h \
|
||||
$$PWD/unsavedfiledata.h \
|
||||
|
||||
@@ -163,8 +163,6 @@ QtcPlugin {
|
||||
"diagnostic.h",
|
||||
"fastindexer.cpp",
|
||||
"fastindexer.h",
|
||||
"liveunitsmanager.cpp",
|
||||
"liveunitsmanager.h",
|
||||
"pchinfo.cpp",
|
||||
"pchinfo.h",
|
||||
"pchmanager.cpp",
|
||||
|
||||
@@ -58,11 +58,6 @@ bool ClangCodeModelPlugin::initialize(const QStringList &arguments, QString *err
|
||||
|
||||
ClangCodeModel::Internal::initializeClang();
|
||||
|
||||
connect(Core::EditorManager::instance(), SIGNAL(editorAboutToClose(Core::IEditor*)),
|
||||
&m_liveUnitsManager, SLOT(editorAboutToClose(Core::IEditor*)));
|
||||
connect(Core::EditorManager::instance(), SIGNAL(editorOpened(Core::IEditor*)),
|
||||
&m_liveUnitsManager, SLOT(editorOpened(Core::IEditor*)));
|
||||
|
||||
PCHManager *pchManager = new PCHManager(this);
|
||||
FastIndexer *fastIndexer = 0;
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#define CLANGPLUGIN_H
|
||||
|
||||
#include "clangmodelmanagersupport.h"
|
||||
#include "liveunitsmanager.h"
|
||||
|
||||
#ifdef CLANG_INDEXING
|
||||
# include "clangindexer.h"
|
||||
@@ -53,7 +52,6 @@ public:
|
||||
void extensionsInitialized();
|
||||
|
||||
private:
|
||||
LiveUnitsManager m_liveUnitsManager;
|
||||
QScopedPointer<ModelManagerSupport> m_modelManagerSupport;
|
||||
#ifdef CLANG_INDEXING
|
||||
QScopedPointer<ClangIndexer> m_indexer;
|
||||
|
||||
@@ -50,6 +50,7 @@ class ClangCodeModel::ClangCompleter::PrivateData
|
||||
public:
|
||||
PrivateData()
|
||||
: m_mutex(QMutex::Recursive)
|
||||
, m_unit(Internal::Unit::create())
|
||||
, m_isSignalSlotCompletion(false)
|
||||
{
|
||||
}
|
||||
@@ -60,8 +61,8 @@ public:
|
||||
|
||||
bool parseFromFile(const Internal::UnsavedFiles &unsavedFiles)
|
||||
{
|
||||
Q_ASSERT(!m_unit.isLoaded());
|
||||
if (m_unit.fileName().isEmpty())
|
||||
Q_ASSERT(!m_unit->isLoaded());
|
||||
if (m_unit->fileName().isEmpty())
|
||||
return false;
|
||||
|
||||
unsigned opts = clang_defaultEditingTranslationUnitOptions();
|
||||
@@ -69,16 +70,16 @@ public:
|
||||
opts |= CXTranslationUnit_CacheCompletionResults;
|
||||
opts |= CXTranslationUnit_IncludeBriefCommentsInCodeCompletion;
|
||||
#endif
|
||||
m_unit.setManagementOptions(opts);
|
||||
m_unit->setManagementOptions(opts);
|
||||
|
||||
m_unit.setUnsavedFiles(unsavedFiles);
|
||||
m_unit.parse();
|
||||
return m_unit.isLoaded();
|
||||
m_unit->setUnsavedFiles(unsavedFiles);
|
||||
m_unit->parse();
|
||||
return m_unit->isLoaded();
|
||||
}
|
||||
|
||||
public:
|
||||
QMutex m_mutex;
|
||||
Internal::Unit m_unit;
|
||||
Internal::Unit::Ptr m_unit;
|
||||
bool m_isSignalSlotCompletion;
|
||||
};
|
||||
|
||||
@@ -119,26 +120,26 @@ ClangCompleter::~ClangCompleter()
|
||||
|
||||
QString ClangCompleter::fileName() const
|
||||
{
|
||||
return d->m_unit.fileName();
|
||||
return d->m_unit->fileName();
|
||||
}
|
||||
|
||||
void ClangCompleter::setFileName(const QString &fileName)
|
||||
{
|
||||
if (d->m_unit.fileName() != fileName) {
|
||||
d->m_unit = Internal::Unit(fileName);
|
||||
if (d->m_unit->fileName() != fileName) {
|
||||
d->m_unit = Internal::Unit::create(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
QStringList ClangCompleter::options() const
|
||||
{
|
||||
return d->m_unit.compilationOptions();
|
||||
return d->m_unit->compilationOptions();
|
||||
}
|
||||
|
||||
void ClangCompleter::setOptions(const QStringList &options) const
|
||||
{
|
||||
if (d->m_unit.compilationOptions() != options) {
|
||||
d->m_unit.setCompilationOptions(options);
|
||||
d->m_unit.unload();
|
||||
if (d->m_unit->compilationOptions() != options) {
|
||||
d->m_unit->setCompilationOptions(options);
|
||||
d->m_unit->unload();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,12 +155,12 @@ void ClangCompleter::setSignalSlotCompletion(bool isSignalSlot)
|
||||
|
||||
bool ClangCompleter::reparse(const UnsavedFiles &unsavedFiles)
|
||||
{
|
||||
if (!d->m_unit.isLoaded())
|
||||
if (!d->m_unit->isLoaded())
|
||||
return d->parseFromFile(unsavedFiles);
|
||||
|
||||
d->m_unit.setUnsavedFiles(unsavedFiles);
|
||||
d->m_unit.reparse();
|
||||
return d->m_unit.isLoaded();
|
||||
d->m_unit->setUnsavedFiles(unsavedFiles);
|
||||
d->m_unit->reparse();
|
||||
return d->m_unit->isLoaded();
|
||||
}
|
||||
|
||||
QList<CodeCompletionResult> ClangCompleter::codeCompleteAt(unsigned line,
|
||||
@@ -170,13 +171,13 @@ QList<CodeCompletionResult> ClangCompleter::codeCompleteAt(unsigned line,
|
||||
QTime t;t.start();
|
||||
#endif // TIME_COMPLETION
|
||||
|
||||
if (!d->m_unit.isLoaded())
|
||||
if (!d->m_unit->isLoaded())
|
||||
if (!d->parseFromFile(unsavedFiles))
|
||||
return QList<CodeCompletionResult>();
|
||||
|
||||
ScopedCXCodeCompleteResults results;
|
||||
d->m_unit.setUnsavedFiles(unsavedFiles);
|
||||
d->m_unit.codeCompleteAt(line, column, results);
|
||||
d->m_unit->setUnsavedFiles(unsavedFiles);
|
||||
d->m_unit->codeCompleteAt(line, column, results);
|
||||
|
||||
QList<CodeCompletionResult> completions;
|
||||
if (results) {
|
||||
@@ -198,7 +199,7 @@ bool ClangCompleter::objcEnabled() const
|
||||
static const QString objcppOption = QLatin1String("-ObjC++");
|
||||
static const QString objcOption = QLatin1String("-ObjC");
|
||||
|
||||
QStringList options = d->m_unit.compilationOptions();
|
||||
QStringList options = d->m_unit->compilationOptions();
|
||||
return options.contains(objcOption) || options.contains(objcppOption);
|
||||
}
|
||||
|
||||
|
||||
@@ -147,11 +147,11 @@ void ClangIndexer::onAboutToSaveSession()
|
||||
m_clangIndexer->finalize();
|
||||
}
|
||||
|
||||
void ClangIndexer::indexNow(const ClangCodeModel::Internal::Unit &unit)
|
||||
void ClangIndexer::indexNow(Unit::Ptr unit)
|
||||
{
|
||||
typedef CppTools::ProjectPart ProjectPart;
|
||||
|
||||
QString file = unit.fileName();
|
||||
QString file = unit->fileName();
|
||||
CppTools::CppModelManagerInterface *mmi = CppTools::CppModelManagerInterface::instance();
|
||||
const QList<ProjectPart::Ptr> &parts = mmi->projectPart(file);
|
||||
ProjectPart::Ptr part;
|
||||
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
|
||||
void match(ClangSymbolSearcher *searcher) const;
|
||||
|
||||
void indexNow(const Unit &unit);
|
||||
void indexNow(Unit::Ptr unit);
|
||||
|
||||
public slots:
|
||||
void onAboutToLoadSession(const QString &sessionName);
|
||||
|
||||
@@ -40,7 +40,7 @@ class FastIndexer
|
||||
public:
|
||||
virtual ~FastIndexer() = 0;
|
||||
|
||||
virtual void indexNow(const Unit &unit) = 0;
|
||||
virtual void indexNow(Unit::Ptr unit) = 0;
|
||||
};
|
||||
|
||||
} // Internal namespace
|
||||
|
||||
@@ -86,11 +86,12 @@ struct IndexingResult
|
||||
typedef CppTools::ProjectPart ProjectPart;
|
||||
|
||||
IndexingResult()
|
||||
: m_unit(Unit::create())
|
||||
{}
|
||||
|
||||
IndexingResult(const QVector<Symbol> &symbol,
|
||||
const QSet<QString> &processedFiles,
|
||||
const Unit &unit,
|
||||
const Unit::Ptr &unit,
|
||||
const ProjectPart::Ptr &projectPart)
|
||||
: m_symbolsInfo(symbol)
|
||||
, m_processedFiles(processedFiles)
|
||||
@@ -100,7 +101,7 @@ struct IndexingResult
|
||||
|
||||
QVector<Symbol> m_symbolsInfo;
|
||||
QSet<QString> m_processedFiles;
|
||||
Unit m_unit;
|
||||
Unit::Ptr m_unit;
|
||||
ProjectPart::Ptr m_projectPart;
|
||||
};
|
||||
|
||||
@@ -259,7 +260,7 @@ protected:
|
||||
foreach (const QString &fn, m_allFiles.keys()) {
|
||||
QVector<ClangCodeModel::Symbol> symbols; unfoldSymbols(symbols, fn);
|
||||
QSet<QString> processedFiles = QSet<QString>::fromList(m_allFiles.keys());
|
||||
Unit unit(fn);
|
||||
Unit::Ptr unit = Unit::create(fn);
|
||||
IndexingResult indexingResult(symbols, processedFiles, unit, projectPart);
|
||||
indexingResults.append(indexingResult);
|
||||
|
||||
@@ -714,10 +715,14 @@ void IndexerPrivate::runCore(const QHash<QString, FileData> & /*headers*/,
|
||||
typedef QHash<QString, FileData>::const_iterator FileContIt;
|
||||
QHash<ProjectPart::Ptr, QList<IndexerPrivate::FileData> > parts;
|
||||
typedef QHash<ProjectPart::Ptr, QList<IndexerPrivate::FileData> >::Iterator PartIter;
|
||||
LiveUnitsManager *lum = LiveUnitsManager::instance();
|
||||
|
||||
QList<Core::IDocument *> docs = Core::EditorManager::documentModel()->openedDocuments();
|
||||
QSet<QString> openDocs;
|
||||
foreach (Core::IDocument *doc, docs)
|
||||
openDocs.insert(doc->filePath());
|
||||
|
||||
for (FileContIt tit = impls.begin(), eit = impls.end(); tit != eit; ++tit) {
|
||||
if (!tit->m_upToDate && !lum->isTracking(tit.key())) {
|
||||
if (!tit->m_upToDate && openDocs.contains(tit.key())) {
|
||||
const IndexerPrivate::FileData &fd = tit.value();
|
||||
parts[fd.m_projectPart].append(fd);
|
||||
}
|
||||
@@ -1278,7 +1283,7 @@ void Indexer::match(ClangSymbolSearcher *searcher) const
|
||||
m_d->match(searcher);
|
||||
}
|
||||
|
||||
void Indexer::runQuickIndexing(const Unit &unit, const CppTools::ProjectPart::Ptr &part)
|
||||
void Indexer::runQuickIndexing(Unit::Ptr unit, const CppTools::ProjectPart::Ptr &part)
|
||||
{
|
||||
m_d->runQuickIndexing(unit, part);
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ public:
|
||||
|
||||
void match(Internal::ClangSymbolSearcher *searcher) const;
|
||||
|
||||
void runQuickIndexing(const Internal::Unit &unit, const ProjectPart::Ptr &part);
|
||||
void runQuickIndexing(Internal::Unit::Ptr unit, const ProjectPart::Ptr &part);
|
||||
|
||||
signals:
|
||||
void indexingStarted(QFuture<void> future);
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** 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 Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/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 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "liveunitsmanager.h"
|
||||
|
||||
#include <coreplugin/idocument.h>
|
||||
|
||||
using namespace ClangCodeModel;
|
||||
using namespace Internal;
|
||||
|
||||
LiveUnitsManager *LiveUnitsManager::m_instance = 0;
|
||||
|
||||
LiveUnitsManager::LiveUnitsManager()
|
||||
{
|
||||
Q_ASSERT(!m_instance);
|
||||
m_instance = this;
|
||||
|
||||
qRegisterMetaType<ClangCodeModel::Internal::Unit>();
|
||||
}
|
||||
|
||||
LiveUnitsManager::~LiveUnitsManager()
|
||||
{
|
||||
m_instance = 0;
|
||||
}
|
||||
|
||||
void LiveUnitsManager::requestTracking(const QString &fileName)
|
||||
{
|
||||
if (!fileName.isEmpty() && !isTracking(fileName))
|
||||
m_units.insert(fileName, Unit(fileName));
|
||||
}
|
||||
|
||||
void LiveUnitsManager::cancelTrackingRequest(const QString &fileName)
|
||||
{
|
||||
if (!isTracking(fileName))
|
||||
return;
|
||||
|
||||
// If no one else is tracking this particular unit, we remove it.
|
||||
if (m_units[fileName].isUnique())
|
||||
m_units.remove(fileName);
|
||||
}
|
||||
|
||||
void LiveUnitsManager::updateUnit(const QString &fileName, const Unit &unit)
|
||||
{
|
||||
if (!isTracking(fileName))
|
||||
return;
|
||||
|
||||
m_units[fileName] = unit;
|
||||
|
||||
emit unitAvailable(unit);
|
||||
}
|
||||
|
||||
Unit LiveUnitsManager::unit(const QString &fileName)
|
||||
{
|
||||
return m_units.value(fileName);
|
||||
}
|
||||
|
||||
void LiveUnitsManager::editorOpened(Core::IEditor *editor)
|
||||
{
|
||||
requestTracking(editor->document()->filePath());
|
||||
}
|
||||
|
||||
void LiveUnitsManager::editorAboutToClose(Core::IEditor *editor)
|
||||
{
|
||||
cancelTrackingRequest(editor->document()->filePath());
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** 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 Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/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 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef LIVEUNITSMANAGER_H
|
||||
#define LIVEUNITSMANAGER_H
|
||||
|
||||
#include "unit.h"
|
||||
|
||||
#include <coreplugin/editormanager/ieditor.h>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QHash>
|
||||
|
||||
namespace ClangCodeModel {
|
||||
namespace Internal {
|
||||
|
||||
class LiveUnitsManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LiveUnitsManager();
|
||||
~LiveUnitsManager();
|
||||
static LiveUnitsManager *instance()
|
||||
{ return m_instance; }
|
||||
|
||||
void requestTracking(const QString &fileName);
|
||||
bool isTracking(const QString &fileName) const
|
||||
{ return m_units.contains(fileName); }
|
||||
|
||||
void cancelTrackingRequest(const QString &fileName);
|
||||
|
||||
void updateUnit(const QString &fileName, const Unit &unit);
|
||||
Unit unit(const QString &fileName);
|
||||
|
||||
public slots:
|
||||
void editorOpened(Core::IEditor *editor);
|
||||
void editorAboutToClose(Core::IEditor *editor);
|
||||
|
||||
signals:
|
||||
void unitAvailable(const ClangCodeModel::Internal::Unit &unit);
|
||||
|
||||
private:
|
||||
static LiveUnitsManager *m_instance;
|
||||
QHash<QString, Unit> m_units;
|
||||
};
|
||||
|
||||
} // Internal
|
||||
} // ClangCodeModel
|
||||
|
||||
#endif // LIVEUNITSMANAGER_H
|
||||
@@ -61,7 +61,7 @@ void SemanticMarker::setFileName(const QString &fileName)
|
||||
QStringList oldOptions;
|
||||
if (m_unit)
|
||||
oldOptions = m_unit->compilationOptions();
|
||||
m_unit.reset(new Unit(fileName));
|
||||
m_unit = Unit::create(fileName);
|
||||
if (!oldOptions.isEmpty())
|
||||
m_unit->setCompilationOptions(oldOptions);
|
||||
|
||||
@@ -499,7 +499,7 @@ QList<SourceMarker> SemanticMarker::sourceMarkersInRange(unsigned firstLine,
|
||||
return result;
|
||||
}
|
||||
|
||||
Unit SemanticMarker::unit() const
|
||||
Unit::Ptr SemanticMarker::unit() const
|
||||
{
|
||||
return *m_unit;
|
||||
return m_unit;
|
||||
}
|
||||
|
||||
@@ -46,10 +46,6 @@
|
||||
|
||||
namespace ClangCodeModel {
|
||||
|
||||
namespace Internal {
|
||||
class Unit;
|
||||
}
|
||||
|
||||
class CLANG_EXPORT SemanticMarker
|
||||
{
|
||||
Q_DISABLE_COPY(SemanticMarker)
|
||||
@@ -78,11 +74,11 @@ public:
|
||||
QList<SourceMarker> sourceMarkersInRange(unsigned firstLine,
|
||||
unsigned lastLine);
|
||||
|
||||
Internal::Unit unit() const;
|
||||
Internal::Unit::Ptr unit() const;
|
||||
|
||||
private:
|
||||
mutable QMutex m_mutex;
|
||||
QScopedPointer<Internal::Unit> m_unit;
|
||||
Internal::Unit::Ptr m_unit;
|
||||
};
|
||||
|
||||
} // namespace ClangCodeModel
|
||||
|
||||
@@ -30,14 +30,12 @@
|
||||
#include "unit.h"
|
||||
#include "unsavedfiledata.h"
|
||||
#include "utils_p.h"
|
||||
#include "raii/scopedclangoptions.h"
|
||||
|
||||
#include <clang-c/Index.h>
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QVector>
|
||||
#include <QtCore/QSharedData>
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtAlgorithms>
|
||||
|
||||
#ifdef DEBUG_UNIT_COUNT
|
||||
@@ -46,76 +44,119 @@
|
||||
static QBasicAtomicInt unitDataCount = Q_BASIC_ATOMIC_INITIALIZER(0);
|
||||
#endif // DEBUG_UNIT_COUNT
|
||||
|
||||
namespace ClangCodeModel {
|
||||
namespace Internal {
|
||||
|
||||
class UnitData : public QSharedData
|
||||
{
|
||||
public:
|
||||
UnitData();
|
||||
UnitData(const QString &fileName);
|
||||
~UnitData();
|
||||
|
||||
void swap(UnitData *unitData);
|
||||
|
||||
void unload();
|
||||
bool isLoaded() const;
|
||||
|
||||
void updateTimeStamp();
|
||||
|
||||
CXIndex m_index;
|
||||
CXTranslationUnit m_tu;
|
||||
QByteArray m_fileName;
|
||||
QStringList m_compOptions;
|
||||
SharedClangOptions m_sharedCompOptions;
|
||||
unsigned m_managementOptions;
|
||||
UnsavedFiles m_unsaved;
|
||||
QDateTime m_timeStamp;
|
||||
};
|
||||
|
||||
} // Internal
|
||||
} // Clang
|
||||
|
||||
using namespace ClangCodeModel;
|
||||
using namespace ClangCodeModel::Internal;
|
||||
|
||||
UnitData::UnitData()
|
||||
static const int DisplayDiagnostics = qgetenv("QTC_CLANG_VERBOSE").isEmpty() ? 0 : 1;
|
||||
|
||||
Unit::Unit()
|
||||
: m_index(0)
|
||||
, m_tu(0)
|
||||
, m_managementOptions(0)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
static const int DisplayDiagnostics = qgetenv("QTC_CLANG_VERBOSE").isEmpty() ? 0 : 1;
|
||||
|
||||
UnitData::UnitData(const QString &fileName)
|
||||
Unit::Unit(const QString &fileName)
|
||||
: m_index(clang_createIndex(/*excludeDeclsFromPCH*/ 1, DisplayDiagnostics))
|
||||
, m_tu(0)
|
||||
, m_fileName(fileName.toUtf8())
|
||||
, m_managementOptions(0)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
UnitData::~UnitData()
|
||||
Unit::~Unit()
|
||||
{
|
||||
unload();
|
||||
clang_disposeIndex(m_index);
|
||||
m_index = 0;
|
||||
}
|
||||
|
||||
void UnitData::swap(UnitData *other)
|
||||
Unit::Ptr Unit::create()
|
||||
{
|
||||
qSwap(m_index, other->m_index);
|
||||
qSwap(m_tu, other->m_tu);
|
||||
qSwap(m_fileName, other->m_fileName);
|
||||
qSwap(m_compOptions, other->m_compOptions);
|
||||
qSwap(m_sharedCompOptions, other->m_sharedCompOptions);
|
||||
qSwap(m_managementOptions, other->m_managementOptions);
|
||||
qSwap(m_unsaved, other->m_unsaved);
|
||||
qSwap(m_timeStamp, other->m_timeStamp);
|
||||
return Unit::Ptr(new Unit);
|
||||
}
|
||||
|
||||
void UnitData::unload()
|
||||
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);
|
||||
}
|
||||
|
||||
UnsavedFiles Unit::unsavedFiles() const
|
||||
{
|
||||
return m_unsaved;
|
||||
}
|
||||
|
||||
void Unit::setUnsavedFiles(const 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);
|
||||
@@ -127,170 +168,25 @@ void UnitData::unload()
|
||||
}
|
||||
}
|
||||
|
||||
bool UnitData::isLoaded() const
|
||||
{
|
||||
return m_tu && m_index;
|
||||
}
|
||||
|
||||
void UnitData::updateTimeStamp()
|
||||
{
|
||||
m_timeStamp = QDateTime::currentDateTime();
|
||||
}
|
||||
|
||||
Unit::Unit()
|
||||
: m_data(new UnitData)
|
||||
{}
|
||||
|
||||
Unit::Unit(const QString &fileName)
|
||||
: m_data(new UnitData(fileName))
|
||||
{}
|
||||
|
||||
Unit::Unit(const Unit &unit)
|
||||
: m_data(unit.m_data)
|
||||
{}
|
||||
|
||||
Unit &Unit::operator =(const Unit &unit)
|
||||
{
|
||||
if (this != &unit)
|
||||
m_data = unit.m_data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Unit::~Unit()
|
||||
{}
|
||||
|
||||
const QString Unit::fileName() const
|
||||
{
|
||||
const QByteArray &name = m_data->m_fileName;
|
||||
return QString::fromUtf8(name.data(), name.size());
|
||||
}
|
||||
|
||||
bool Unit::isLoaded() const
|
||||
{
|
||||
return m_data->isLoaded();
|
||||
}
|
||||
|
||||
const QDateTime &Unit::timeStamp() const
|
||||
{
|
||||
return m_data->m_timeStamp;
|
||||
}
|
||||
|
||||
QStringList Unit::compilationOptions() const
|
||||
{
|
||||
return m_data->m_compOptions;
|
||||
}
|
||||
|
||||
void Unit::setCompilationOptions(const QStringList &compOptions)
|
||||
{
|
||||
m_data->m_compOptions = compOptions;
|
||||
m_data->m_sharedCompOptions.reloadOptions(compOptions);
|
||||
}
|
||||
|
||||
UnsavedFiles Unit::unsavedFiles() const
|
||||
{
|
||||
return m_data->m_unsaved;
|
||||
}
|
||||
|
||||
void Unit::setUnsavedFiles(const UnsavedFiles &unsavedFiles)
|
||||
{
|
||||
m_data->m_unsaved = unsavedFiles;
|
||||
}
|
||||
|
||||
unsigned Unit::managementOptions() const
|
||||
{
|
||||
return m_data->m_managementOptions;
|
||||
}
|
||||
|
||||
void Unit::setManagementOptions(unsigned managementOptions)
|
||||
{
|
||||
m_data->m_managementOptions = managementOptions;
|
||||
}
|
||||
|
||||
bool Unit::isUnique() const
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
return m_data->ref.load() == 1;
|
||||
#else
|
||||
return m_data->ref == 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Unit::makeUnique()
|
||||
{
|
||||
UnitData *uniqueData = new UnitData;
|
||||
m_data->swap(uniqueData); // Notice we swap the data itself and not the shared pointer.
|
||||
m_data = QExplicitlySharedDataPointer<UnitData>(uniqueData);
|
||||
}
|
||||
|
||||
void Unit::parse()
|
||||
{
|
||||
m_data->unload();
|
||||
|
||||
m_data->updateTimeStamp();
|
||||
|
||||
UnsavedFileData unsaved(m_data->m_unsaved);
|
||||
m_data->m_tu = clang_parseTranslationUnit(m_data->m_index,
|
||||
m_data->m_fileName.constData(),
|
||||
m_data->m_sharedCompOptions.data(),
|
||||
m_data->m_sharedCompOptions.size(),
|
||||
unsaved.files(),
|
||||
unsaved.count(),
|
||||
m_data->m_managementOptions);
|
||||
}
|
||||
|
||||
void Unit::reparse()
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
UnsavedFileData unsaved(m_data->m_unsaved);
|
||||
const unsigned opts = clang_defaultReparseOptions(m_data->m_tu);
|
||||
if (clang_reparseTranslationUnit(m_data->m_tu, unsaved.count(), unsaved.files(), opts) != 0)
|
||||
m_data->unload();
|
||||
}
|
||||
|
||||
void Unit::create()
|
||||
{
|
||||
// @TODO
|
||||
}
|
||||
|
||||
void Unit::createFromSourceFile()
|
||||
{
|
||||
// @TODO
|
||||
}
|
||||
|
||||
int Unit::save(const QString &unitFileName)
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return clang_saveTranslationUnit(m_data->m_tu,
|
||||
unitFileName.toUtf8().constData(),
|
||||
clang_defaultSaveOptions(m_data->m_tu));
|
||||
}
|
||||
|
||||
void Unit::unload()
|
||||
{
|
||||
m_data->unload();
|
||||
}
|
||||
|
||||
CXFile Unit::getFile() const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return clang_getFile(m_data->m_tu, m_data->m_fileName.constData());
|
||||
return clang_getFile(m_tu, m_fileName.constData());
|
||||
}
|
||||
|
||||
CXCursor Unit::getCursor(const CXSourceLocation &location) const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return clang_getCursor(m_data->m_tu, location);
|
||||
return clang_getCursor(m_tu, location);
|
||||
}
|
||||
|
||||
CXSourceLocation Unit::getLocation(const CXFile &file, unsigned line, unsigned column) const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return clang_getLocation(m_data->m_tu, file, line, column);
|
||||
return clang_getLocation(m_tu, file, line, column);
|
||||
}
|
||||
|
||||
void Unit::codeCompleteAt(unsigned line, unsigned column, ScopedCXCodeCompleteResults &results)
|
||||
@@ -300,10 +196,11 @@ void Unit::codeCompleteAt(unsigned line, unsigned column, ScopedCXCodeCompleteRe
|
||||
flags |= CXCodeComplete_IncludeBriefComments;
|
||||
#endif
|
||||
|
||||
UnsavedFileData unsaved(m_data->m_unsaved);
|
||||
results.reset(clang_codeCompleteAt(m_data->m_tu, m_data->m_fileName.constData(),
|
||||
UnsavedFileData unsaved(m_unsaved);
|
||||
results.reset(clang_codeCompleteAt(m_tu, m_fileName.constData(),
|
||||
line, column,
|
||||
unsaved.files(), unsaved.count(), flags));
|
||||
unsaved.files(), unsaved.count(),
|
||||
flags));
|
||||
}
|
||||
|
||||
void Unit::tokenize(CXSourceRange range, CXToken **tokens, unsigned *tokenCount) const
|
||||
@@ -313,21 +210,21 @@ void Unit::tokenize(CXSourceRange range, CXToken **tokens, unsigned *tokenCount)
|
||||
Q_ASSERT(tokenCount);
|
||||
Q_ASSERT(!clang_Range_isNull(range));
|
||||
|
||||
clang_tokenize(m_data->m_tu, range, tokens, tokenCount);
|
||||
clang_tokenize(m_tu, range, tokens, tokenCount);
|
||||
}
|
||||
|
||||
void Unit::disposeTokens(CXToken *tokens, unsigned tokenCount) const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
clang_disposeTokens(m_data->m_tu, tokens, tokenCount);
|
||||
clang_disposeTokens(m_tu, tokens, tokenCount);
|
||||
}
|
||||
|
||||
CXSourceRange Unit::getTokenExtent(const CXToken &token) const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return clang_getTokenExtent(m_data->m_tu, token);
|
||||
return clang_getTokenExtent(m_tu, token);
|
||||
}
|
||||
|
||||
void Unit::annotateTokens(CXToken *tokens, unsigned tokenCount, CXCursor *cursors) const
|
||||
@@ -336,63 +233,68 @@ void Unit::annotateTokens(CXToken *tokens, unsigned tokenCount, CXCursor *cursor
|
||||
Q_ASSERT(tokens);
|
||||
Q_ASSERT(cursors);
|
||||
|
||||
clang_annotateTokens(m_data->m_tu, tokens, tokenCount, cursors);
|
||||
clang_annotateTokens(m_tu, tokens, tokenCount, cursors);
|
||||
}
|
||||
|
||||
CXTranslationUnit Unit::clangTranslationUnit() const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return m_data->m_tu;
|
||||
return m_tu;
|
||||
}
|
||||
|
||||
CXIndex Unit::clangIndex() const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return m_data->m_index;
|
||||
return m_index;
|
||||
}
|
||||
|
||||
QString Unit::getTokenSpelling(const CXToken &tok) const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return getQString(clang_getTokenSpelling(m_data->m_tu, tok));
|
||||
return getQString(clang_getTokenSpelling(m_tu, tok));
|
||||
}
|
||||
|
||||
CXCursor Unit::getTranslationUnitCursor() const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return clang_getTranslationUnitCursor(m_data->m_tu);
|
||||
return clang_getTranslationUnitCursor(m_tu);
|
||||
}
|
||||
|
||||
CXString Unit::getTranslationUnitSpelling() const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return clang_getTranslationUnitSpelling(m_data->m_tu);
|
||||
return clang_getTranslationUnitSpelling(m_tu);
|
||||
}
|
||||
|
||||
void Unit::getInclusions(CXInclusionVisitor visitor, CXClientData clientData) const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
clang_getInclusions(m_data->m_tu, visitor, clientData);
|
||||
clang_getInclusions(m_tu, visitor, clientData);
|
||||
}
|
||||
|
||||
unsigned Unit::getNumDiagnostics() const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return clang_getNumDiagnostics(m_data->m_tu);
|
||||
return clang_getNumDiagnostics(m_tu);
|
||||
}
|
||||
|
||||
CXDiagnostic Unit::getDiagnostic(unsigned index) const
|
||||
{
|
||||
Q_ASSERT(isLoaded());
|
||||
|
||||
return clang_getDiagnostic(m_data->m_tu, index);
|
||||
return clang_getDiagnostic(m_tu, index);
|
||||
}
|
||||
|
||||
void Unit::updateTimeStamp()
|
||||
{
|
||||
m_timeStamp = QDateTime::currentDateTime();
|
||||
}
|
||||
|
||||
IdentifierTokens::IdentifierTokens(const Unit &unit, unsigned firstLine, unsigned lastLine)
|
||||
|
||||
@@ -31,10 +31,11 @@
|
||||
#define UNIT_H
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#include "raii/scopedclangoptions.h"
|
||||
#include "cxraii.h"
|
||||
|
||||
#include <QExplicitlySharedDataPointer>
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QSharedPointer>
|
||||
#include <QMetaType>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
@@ -63,8 +64,6 @@ class UnitData;
|
||||
* - 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.
|
||||
* - The data of the TU is shared.
|
||||
*
|
||||
*
|
||||
* @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
|
||||
@@ -74,13 +73,18 @@ class UnitData;
|
||||
*/
|
||||
class Unit
|
||||
{
|
||||
public:
|
||||
Q_DISABLE_COPY(Unit)
|
||||
|
||||
Unit();
|
||||
explicit Unit(const QString &fileName);
|
||||
Unit(const Unit &unit);
|
||||
Unit &operator=(const Unit &unit);
|
||||
|
||||
public:
|
||||
~Unit();
|
||||
|
||||
typedef QSharedPointer<Unit> Ptr;
|
||||
static Ptr create();
|
||||
static Ptr create(const QString &fileName);
|
||||
|
||||
bool isLoaded() const;
|
||||
|
||||
const QString fileName() const;
|
||||
@@ -96,20 +100,11 @@ public:
|
||||
unsigned managementOptions() const;
|
||||
void setManagementOptions(unsigned managementOptions);
|
||||
|
||||
// Sharing control facilities
|
||||
// Method isUnique is just like an "isDetached", however makeUnique is mostly some kind
|
||||
// of "detach" but which actually moves the data to this particular instance, invalidating
|
||||
// then all the other shares.
|
||||
bool isUnique() const;
|
||||
void makeUnique();
|
||||
|
||||
// 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();
|
||||
void create();
|
||||
void createFromSourceFile();
|
||||
int save(const QString &unitFileName);
|
||||
void unload();
|
||||
|
||||
@@ -152,7 +147,16 @@ public:
|
||||
QString getTokenSpelling(const CXToken &tok) const;
|
||||
|
||||
private:
|
||||
QExplicitlySharedDataPointer<UnitData> m_data;
|
||||
void updateTimeStamp();
|
||||
|
||||
CXIndex m_index;
|
||||
CXTranslationUnit m_tu;
|
||||
QByteArray m_fileName;
|
||||
QStringList m_compOptions;
|
||||
SharedClangOptions m_sharedCompOptions;
|
||||
unsigned m_managementOptions;
|
||||
UnsavedFiles m_unsaved;
|
||||
QDateTime m_timeStamp;
|
||||
};
|
||||
|
||||
class IdentifierTokens
|
||||
@@ -190,6 +194,6 @@ private:
|
||||
} // Internal
|
||||
} // Clang
|
||||
|
||||
Q_DECLARE_METATYPE(ClangCodeModel::Internal::Unit)
|
||||
Q_DECLARE_METATYPE(ClangCodeModel::Internal::Unit::Ptr)
|
||||
|
||||
#endif // UNIT_H
|
||||
|
||||
@@ -48,16 +48,16 @@ QPair<bool, QStringList> precompile(const PchInfo::Ptr &pchInfo)
|
||||
|
||||
bool ok = false;
|
||||
|
||||
Internal::Unit unit(pchInfo->inputFileName());
|
||||
unit.setCompilationOptions(pchInfo->options());
|
||||
Internal::Unit::Ptr unit = Internal::Unit::create(pchInfo->inputFileName());
|
||||
unit->setCompilationOptions(pchInfo->options());
|
||||
|
||||
unsigned parseOpts = CXTranslationUnit_ForSerialization
|
||||
| CXTranslationUnit_Incomplete;
|
||||
unit.setManagementOptions(parseOpts);
|
||||
unit->setManagementOptions(parseOpts);
|
||||
|
||||
unit.parse();
|
||||
if (unit.isLoaded())
|
||||
ok = CXSaveError_None == unit.save(pchInfo->fileName());
|
||||
unit->parse();
|
||||
if (unit->isLoaded())
|
||||
ok = CXSaveError_None == unit->save(pchInfo->fileName());
|
||||
|
||||
return qMakePair(ok, Internal::formattedDiagnostics(unit));
|
||||
}
|
||||
|
||||
@@ -96,15 +96,15 @@ QString normalizeFileName(const QFileInfo &fileInfo)
|
||||
return QDir::cleanPath(fileInfo.absoluteFilePath());
|
||||
}
|
||||
|
||||
QStringList formattedDiagnostics(const Unit &unit)
|
||||
QStringList formattedDiagnostics(const Unit::Ptr &unit)
|
||||
{
|
||||
QStringList diags;
|
||||
if (!unit.isLoaded())
|
||||
if (!unit->isLoaded())
|
||||
return diags;
|
||||
|
||||
const unsigned count = unit.getNumDiagnostics();
|
||||
const unsigned count = unit->getNumDiagnostics();
|
||||
for (unsigned i = 0; i < count; ++i) {
|
||||
CXDiagnostic diag = unit.getDiagnostic(i);
|
||||
CXDiagnostic diag = unit->getDiagnostic(i);
|
||||
|
||||
unsigned opt = CXDiagnostic_DisplaySourceLocation
|
||||
| CXDiagnostic_DisplayColumn
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#define CLANG_REUSE_H
|
||||
|
||||
#include "sourcelocation.h"
|
||||
#include "unit.h"
|
||||
|
||||
#include <clang-c/Index.h>
|
||||
|
||||
@@ -43,8 +44,6 @@ QT_END_NAMESPACE
|
||||
namespace ClangCodeModel {
|
||||
namespace Internal {
|
||||
|
||||
class Unit;
|
||||
|
||||
QString getQString(const CXString &cxString, bool disposeCXString = true);
|
||||
|
||||
SourceLocation getInstantiatonLocation(const CXSourceLocation &loc); // Deprecated
|
||||
@@ -58,7 +57,7 @@ SourceLocation getExpansionLocation(const CXSourceLocation &loc);
|
||||
QString normalizeFileName(const QString &fileName);
|
||||
QString normalizeFileName(const QFileInfo &fileInfo);
|
||||
|
||||
QStringList formattedDiagnostics(const Unit &unit);
|
||||
QStringList formattedDiagnostics(const Unit::Ptr &unit);
|
||||
|
||||
} // Internal
|
||||
} // ClangCodeModel
|
||||
|
||||
Reference in New Issue
Block a user