diff options
author | Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> | 2015-12-02 18:42:05 +0100 |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> | 2015-12-02 18:42:05 +0100 |
commit | 100ea30a1a5ccb0af4adafbf08b8fa89fe3c0ee7 (patch) | |
tree | 0b2aca7b1533ac466e7d2312a6bd3fa1a0282ea1 /src | |
parent | f86ebcbf22d7df6be60f1fc5c9f0f30a76e104d6 (diff) | |
parent | e4be9edc4d538465338b8981294aa414a43b7255 (diff) | |
download | qt-creator-100ea30a1a5ccb0af4adafbf08b8fa89fe3c0ee7.tar.gz |
Merge remote-tracking branch 'origin/3.6'
Conflicts:
src/plugins/projectexplorer/toolchainmanager.cpp
src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp
Change-Id: Id736c6922670c921c689219cb817b1541eaaf304
Diffstat (limited to 'src')
143 files changed, 1708 insertions, 7820 deletions
diff --git a/src/libs/3rdparty/cplusplus/Bind.cpp b/src/libs/3rdparty/cplusplus/Bind.cpp index 63940d19dd..e5802d4428 100644 --- a/src/libs/3rdparty/cplusplus/Bind.cpp +++ b/src/libs/3rdparty/cplusplus/Bind.cpp @@ -30,6 +30,7 @@ #include "cppassert.h" +#include <algorithm> #include <vector> #include <string> #include <memory> diff --git a/src/libs/3rdparty/cplusplus/Templates.cpp b/src/libs/3rdparty/cplusplus/Templates.cpp index 3b8ae9a23f..61c6e612ae 100644 --- a/src/libs/3rdparty/cplusplus/Templates.cpp +++ b/src/libs/3rdparty/cplusplus/Templates.cpp @@ -27,6 +27,7 @@ #include "cppassert.h" +#include <algorithm> using namespace CPlusPlus; diff --git a/src/libs/3rdparty/sqlite/sqlite.pri b/src/libs/3rdparty/sqlite/sqlite.pri index 896616f736..469a76955e 100644 --- a/src/libs/3rdparty/sqlite/sqlite.pri +++ b/src/libs/3rdparty/sqlite/sqlite.pri @@ -4,12 +4,8 @@ HEADERS += $$PWD/okapi_bm25.h \ $$PWD/sqlite3.h \ $$PWD/sqlite3ext.h - SOURCES += $$PWD/sqlite3.c -win32:DEFINES += SQLITE_API=__declspec(dllexport) -unix:DEFINES += SQLITE_API=\"__attribute__((visibility(\\\"default\\\")))\" - gcc { QMAKE_CFLAGS_WARN_ON = -w } diff --git a/src/libs/clangbackendipc/clangbackendipc-lib.pri b/src/libs/clangbackendipc/clangbackendipc-lib.pri index 3084a13761..cbe5ad01fe 100644 --- a/src/libs/clangbackendipc/clangbackendipc-lib.pri +++ b/src/libs/clangbackendipc/clangbackendipc-lib.pri @@ -6,8 +6,6 @@ contains(CONFIG, dll) { QT += network -DEFINES += CLANGBACKENDIPC_LIBRARY - INCLUDEPATH += $$PWD SOURCES += $$PWD/ipcserverinterface.cpp \ @@ -44,10 +42,13 @@ SOURCES += $$PWD/ipcserverinterface.cpp \ $$PWD/sourcelocationcontainer.cpp \ $$PWD/fixitcontainer.cpp \ $$PWD/requestdiagnosticsmessage.cpp \ + $$PWD/requesthighlightingmessage.cpp \ $$PWD/registerunsavedfilesforeditormessage.cpp \ $$PWD/unregisterunsavedfilesforeditormessage.cpp \ $$PWD/updatetranslationunitsforeditormessage.cpp \ - $$PWD/updatevisibletranslationunitsmessage.cpp + $$PWD/updatevisibletranslationunitsmessage.cpp \ + $$PWD/highlightingchangedmessage.cpp \ + $$PWD/highlightingmarkcontainer.cpp HEADERS += \ $$PWD/ipcserverinterface.h \ @@ -86,9 +87,12 @@ HEADERS += \ $$PWD/sourcelocationcontainer.h \ $$PWD/fixitcontainer.h \ $$PWD/requestdiagnosticsmessage.h \ + $$PWD/requesthighlightingmessage.h \ $$PWD/registerunsavedfilesforeditormessage.h \ $$PWD/unregisterunsavedfilesforeditormessage.h \ $$PWD/updatetranslationunitsforeditormessage.h \ - $$PWD/updatevisibletranslationunitsmessage.h + $$PWD/updatevisibletranslationunitsmessage.h \ + $$PWD/highlightingchangedmessage.h \ + $$PWD/highlightingmarkcontainer.h contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols diff --git a/src/libs/clangbackendipc/clangbackendipc_global.h b/src/libs/clangbackendipc/clangbackendipc_global.h index c9851069b5..3efaf48c3c 100644 --- a/src/libs/clangbackendipc/clangbackendipc_global.h +++ b/src/libs/clangbackendipc/clangbackendipc_global.h @@ -33,8 +33,10 @@ #include <QtCore/qglobal.h> -#if defined(CLANGBACKENDIPC_LIBRARY) +#if defined(CLANGBACKENDIPC_BUILD_LIB) # define CMBIPC_EXPORT Q_DECL_EXPORT +#elif defined(CLANGBACKENDIPC_BUILD_STATIC_LIB) +# define CMBIPC_EXPORT #else # define CMBIPC_EXPORT Q_DECL_IMPORT #endif diff --git a/src/libs/clangbackendipc/cmbmessages.cpp b/src/libs/clangbackendipc/cmbmessages.cpp index d275de5353..c3ce8d0e17 100644 --- a/src/libs/clangbackendipc/cmbmessages.cpp +++ b/src/libs/clangbackendipc/cmbmessages.cpp @@ -43,6 +43,9 @@ #include "diagnosticschangedmessage.h" #include "registerunsavedfilesforeditormessage.h" #include "requestdiagnosticsmessage.h" +#include "requesthighlightingmessage.h" +#include "highlightingchangedmessage.h" +#include "highlightingmarkcontainer.h" #include "projectpartsdonotexistmessage.h" #include "sourcelocationcontainer.h" #include "sourcerangecontainer.h" @@ -83,6 +86,9 @@ void Messages::registerMessages() registerMetaType<RequestDiagnosticsMessage>(); registerMetaType<DiagnosticsChangedMessage>(); + registerMetaType<RequestHighlightingMessage>(); + registerMetaType<HighlightingChangedMessage>(); + registerMetaType<UpdateVisibleTranslationUnitsMessage>(); registerMetaType<CompleteCodeMessage>(); @@ -94,6 +100,7 @@ void Messages::registerMessages() // Containers registerMetaType<DiagnosticContainer>(); + registerMetaType<HighlightingMarkContainer>(); registerMetaType<FileContainer>(); registerMetaType<ProjectPartContainer>(); registerMetaType<SourceLocationContainer>(); diff --git a/src/libs/clangbackendipc/cmbregistertranslationunitsforeditormessage.cpp b/src/libs/clangbackendipc/cmbregistertranslationunitsforeditormessage.cpp index 1c1d0dff52..bfb4fee293 100644 --- a/src/libs/clangbackendipc/cmbregistertranslationunitsforeditormessage.cpp +++ b/src/libs/clangbackendipc/cmbregistertranslationunitsforeditormessage.cpp @@ -39,8 +39,12 @@ namespace ClangBackEnd { -RegisterTranslationUnitForEditorMessage::RegisterTranslationUnitForEditorMessage(const QVector<FileContainer> &fileContainers) - : fileContainers_(fileContainers) +RegisterTranslationUnitForEditorMessage::RegisterTranslationUnitForEditorMessage(const QVector<FileContainer> &fileContainers, + const Utf8String ¤tEditorFilePath, + const Utf8StringVector &visibleEditorFilePaths) + : fileContainers_(fileContainers), + currentEditorFilePath_(currentEditorFilePath), + visibleEditorFilePaths_(visibleEditorFilePaths) { } @@ -49,28 +53,45 @@ const QVector<FileContainer> &RegisterTranslationUnitForEditorMessage::fileConta return fileContainers_; } +const Utf8String &RegisterTranslationUnitForEditorMessage::currentEditorFilePath() const +{ + return currentEditorFilePath_; +} + +const Utf8StringVector &RegisterTranslationUnitForEditorMessage::visibleEditorFilePaths() const +{ + return visibleEditorFilePaths_; +} + QDataStream &operator<<(QDataStream &out, const RegisterTranslationUnitForEditorMessage &message) { out << message.fileContainers_; - + out << message.currentEditorFilePath_; + out << message.visibleEditorFilePaths_; return out; } QDataStream &operator>>(QDataStream &in, RegisterTranslationUnitForEditorMessage &message) { in >> message.fileContainers_; + in >> message.currentEditorFilePath_; + in >> message.visibleEditorFilePaths_; return in; } bool operator==(const RegisterTranslationUnitForEditorMessage &first, const RegisterTranslationUnitForEditorMessage &second) { - return first.fileContainers_ == second.fileContainers_; + return first.fileContainers_ == second.fileContainers_ + && first.currentEditorFilePath_ == second.currentEditorFilePath_ + && first.visibleEditorFilePaths_ == second.visibleEditorFilePaths_; } bool operator<(const RegisterTranslationUnitForEditorMessage &first, const RegisterTranslationUnitForEditorMessage &second) { - return compareContainer(first.fileContainers_, second.fileContainers_); + return compareContainer(first.fileContainers_, second.fileContainers_) + && first.currentEditorFilePath_ < second.currentEditorFilePath_ + && compareContainer(first.visibleEditorFilePaths_, second.visibleEditorFilePaths_); } QDebug operator<<(QDebug debug, const RegisterTranslationUnitForEditorMessage &message) @@ -80,6 +101,11 @@ QDebug operator<<(QDebug debug, const RegisterTranslationUnitForEditorMessage &m for (const FileContainer &fileContainer : message.fileContainers()) debug.nospace() << fileContainer<< ", "; + debug.nospace() << message.currentEditorFilePath() << ", "; + + for (const Utf8String &visibleEditorFilePath : message.visibleEditorFilePaths()) + debug.nospace() << visibleEditorFilePath << ", "; + debug.nospace() << ")"; return debug; @@ -92,6 +118,12 @@ void PrintTo(const RegisterTranslationUnitForEditorMessage &message, ::std::ostr for (const FileContainer &fileContainer : message.fileContainers()) PrintTo(fileContainer, os); + *os << message.currentEditorFilePath().constData() << ", "; + + auto visiblePaths = message.visibleEditorFilePaths(); + + std::copy(visiblePaths.cbegin(), visiblePaths.cend(), std::ostream_iterator<Utf8String>(*os, ", ")); + *os << ")"; } diff --git a/src/libs/clangbackendipc/cmbregistertranslationunitsforeditormessage.h b/src/libs/clangbackendipc/cmbregistertranslationunitsforeditormessage.h index c8411daca3..74920ecab4 100644 --- a/src/libs/clangbackendipc/cmbregistertranslationunitsforeditormessage.h +++ b/src/libs/clangbackendipc/cmbregistertranslationunitsforeditormessage.h @@ -47,12 +47,18 @@ class CMBIPC_EXPORT RegisterTranslationUnitForEditorMessage friend void PrintTo(const RegisterTranslationUnitForEditorMessage &message, ::std::ostream* os); public: RegisterTranslationUnitForEditorMessage() = default; - RegisterTranslationUnitForEditorMessage(const QVector<FileContainer> &fileContainers); + RegisterTranslationUnitForEditorMessage(const QVector<FileContainer> &fileContainers, + const Utf8String ¤tEditorFilePath, + const Utf8StringVector &visibleEditorFilePaths); const QVector<FileContainer> &fileContainers() const; + const Utf8String ¤tEditorFilePath() const; + const Utf8StringVector &visibleEditorFilePaths() const; private: QVector<FileContainer> fileContainers_; + Utf8String currentEditorFilePath_; + Utf8StringVector visibleEditorFilePaths_; }; CMBIPC_EXPORT QDataStream &operator<<(QDataStream &out, const RegisterTranslationUnitForEditorMessage &message); diff --git a/src/libs/clangbackendipc/connectionclient.cpp b/src/libs/clangbackendipc/connectionclient.cpp index f535604168..0e043cb115 100644 --- a/src/libs/clangbackendipc/connectionclient.cpp +++ b/src/libs/clangbackendipc/connectionclient.cpp @@ -37,11 +37,19 @@ #include <QCoreApplication> #include <QProcess> +#include <QTemporaryDir> #include <QThread> namespace ClangBackEnd { namespace { +const QTemporaryDir &temporaryDirectory() +{ + static QTemporaryDir temporaryDirectory(QDir::tempPath() + QStringLiteral("/qtc-clang-XXXXXX")); + + return temporaryDirectory; +} + QString currentProcessId() { return QString::number(QCoreApplication::applicationPid()); @@ -49,7 +57,7 @@ QString currentProcessId() QString connectionName() { - return QStringLiteral("ClangBackEnd-") + currentProcessId(); + return temporaryDirectory().path() + QStringLiteral("/ClangBackEnd-") + currentProcessId(); } } @@ -128,6 +136,20 @@ void ConnectionClient::setProcessAliveTimerInterval(int processTimerInterval) processAliveTimer.setInterval(processTimerInterval); } +QProcessEnvironment ConnectionClient::processEnvironment() const +{ + auto processEnvironment = QProcessEnvironment::systemEnvironment(); + + if (temporaryDirectory().isValid()) { + const QString temporaryDirectoryPath = temporaryDirectory().path(); + processEnvironment.insert(QStringLiteral("TMPDIR"), temporaryDirectoryPath); + processEnvironment.insert(QStringLiteral("TMP"), temporaryDirectoryPath); + processEnvironment.insert(QStringLiteral("TEMP"), temporaryDirectoryPath); + } + + return processEnvironment; +} + void ConnectionClient::startProcess() { TIME_SCOPE_DURATION("ConnectionClient::startProcess"); @@ -135,6 +157,7 @@ void ConnectionClient::startProcess() if (!isProcessIsRunning()) { connectProcessFinished(); connectStandardOutputAndError(); + process()->setProcessEnvironment(processEnvironment()); process()->start(processPath(), {connectionName()}); process()->waitForStarted(); resetProcessAliveTimer(); diff --git a/src/libs/clangbackendipc/connectionclient.h b/src/libs/clangbackendipc/connectionclient.h index bcd83d6767..147c9bd4f8 100644 --- a/src/libs/clangbackendipc/connectionclient.h +++ b/src/libs/clangbackendipc/connectionclient.h @@ -35,6 +35,7 @@ #include "lineprefixer.h" #include <QLocalSocket> +#include <QProcessEnvironment> #include <memory> @@ -100,6 +101,8 @@ private: void ensureMessageIsWritten(); + QProcessEnvironment processEnvironment() const; + private: mutable std::unique_ptr<QProcess> process_; QLocalSocket localSocket; diff --git a/src/libs/clangbackendipc/highlightingchangedmessage.cpp b/src/libs/clangbackendipc/highlightingchangedmessage.cpp new file mode 100644 index 0000000000..b049ebef52 --- /dev/null +++ b/src/libs/clangbackendipc/highlightingchangedmessage.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** 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 "highlightingchangedmessage.h" + +#include "container_common.h" + +#include <QDataStream> +#include <QDebug> + +#include <ostream> + +namespace ClangBackEnd { + +HighlightingChangedMessage::HighlightingChangedMessage(const FileContainer &file, + const QVector<HighlightingMarkContainer> &highlightingMarks, + const QVector<SourceRangeContainer> &skippedPreprocessorRanges) + : file_(file), + highlightingMarks_(highlightingMarks), + skippedPreprocessorRanges_(skippedPreprocessorRanges) +{ +} + +const FileContainer &HighlightingChangedMessage::file() const +{ + return file_; +} + +const QVector<HighlightingMarkContainer> &HighlightingChangedMessage::highlightingMarks() const +{ + return highlightingMarks_; +} + +const QVector<SourceRangeContainer> &HighlightingChangedMessage::skippedPreprocessorRanges() const +{ + return skippedPreprocessorRanges_; +} + +QDataStream &operator<<(QDataStream &out, const HighlightingChangedMessage &message) +{ + out << message.file_; + out << message.highlightingMarks_; + out << message.skippedPreprocessorRanges_; + + return out; +} + +QDataStream &operator>>(QDataStream &in, HighlightingChangedMessage &message) +{ + in >> message.file_; + in >> message.highlightingMarks_; + in >> message.skippedPreprocessorRanges_; + + return in; +} + +bool operator==(const HighlightingChangedMessage &first, const HighlightingChangedMessage &second) +{ + return first.file_ == second.file_ + && first.highlightingMarks_ == second.highlightingMarks_ + && first.skippedPreprocessorRanges_ == second.skippedPreprocessorRanges_; +} + +bool operator<(const HighlightingChangedMessage &first, const HighlightingChangedMessage &second) +{ + return first.file_ < second.file_ + && compareContainer(first.highlightingMarks_, second.highlightingMarks_) + && compareContainer(first.skippedPreprocessorRanges_, second.skippedPreprocessorRanges_); +} + +QDebug operator<<(QDebug debug, const HighlightingChangedMessage &message) +{ + debug.nospace() << "HighlightingChangedMessage(" + << message.file_ + << ", " << message.highlightingMarks_.size() + << ", " << message.skippedPreprocessorRanges_.size() + << ")"; + + return debug; +} + +void PrintTo(const HighlightingChangedMessage &message, ::std::ostream* os) +{ + *os << "HighlightingChangedMessage("; + PrintTo(message.file(), os); + *os << "," << message.highlightingMarks().size(); + *os << "," << message.skippedPreprocessorRanges().size(); + *os << ")"; +} + +} // namespace ClangBackEnd + diff --git a/src/libs/clangbackendipc/highlightingchangedmessage.h b/src/libs/clangbackendipc/highlightingchangedmessage.h new file mode 100644 index 0000000000..6efabe19ee --- /dev/null +++ b/src/libs/clangbackendipc/highlightingchangedmessage.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** 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 CLANGBACKEND_HIGHLIGHTINGCHANGEDMESSAGE_H +#define CLANGBACKEND_HIGHLIGHTINGCHANGEDMESSAGE_H + +#include "clangbackendipc_global.h" +#include "filecontainer.h" +#include "highlightingmarkcontainer.h" +#include "sourcerangecontainer.h" + +#include <QVector> + +namespace ClangBackEnd { + +class CMBIPC_EXPORT HighlightingChangedMessage +{ + friend CMBIPC_EXPORT QDataStream &operator<<(QDataStream &out, const HighlightingChangedMessage &message); + friend CMBIPC_EXPORT QDataStream &operator>>(QDataStream &in, HighlightingChangedMessage &message); + friend CMBIPC_EXPORT bool operator==(const HighlightingChangedMessage &first, const HighlightingChangedMessage &second); + friend CMBIPC_EXPORT bool operator<(const HighlightingChangedMessage &first, const HighlightingChangedMessage &second); + friend CMBIPC_EXPORT QDebug operator<<(QDebug debug, const HighlightingChangedMessage &message); + friend void PrintTo(const HighlightingChangedMessage &message, ::std::ostream* os); + +public: + HighlightingChangedMessage() = default; + HighlightingChangedMessage(const FileContainer &file, + const QVector<HighlightingMarkContainer> &highlightingMarks, + const QVector<SourceRangeContainer> &skippedPreprocessorRanges); + + const FileContainer &file() const; + const QVector<HighlightingMarkContainer> &highlightingMarks() const; + const QVector<SourceRangeContainer> &skippedPreprocessorRanges() const; + +private: + FileContainer file_; + QVector<HighlightingMarkContainer> highlightingMarks_; + QVector<SourceRangeContainer> skippedPreprocessorRanges_; +}; + +CMBIPC_EXPORT QDataStream &operator<<(QDataStream &out, const HighlightingChangedMessage &message); +CMBIPC_EXPORT QDataStream &operator>>(QDataStream &in, HighlightingChangedMessage &message); +CMBIPC_EXPORT bool operator==(const HighlightingChangedMessage &first, const HighlightingChangedMessage &second); +CMBIPC_EXPORT bool operator<(const HighlightingChangedMessage &first, const HighlightingChangedMessage &second); + +CMBIPC_EXPORT QDebug operator<<(QDebug debug, const HighlightingChangedMessage &message); +void PrintTo(const HighlightingChangedMessage &message, ::std::ostream* os); + +} // namespace ClangBackEnd + +Q_DECLARE_METATYPE(ClangBackEnd::HighlightingChangedMessage) + +#endif // CLANGBACKEND_HIGHLIGHTINGCHANGEDMESSAGE_H diff --git a/src/libs/clangbackendipc/highlightingmarkcontainer.cpp b/src/libs/clangbackendipc/highlightingmarkcontainer.cpp new file mode 100644 index 0000000000..efa5b04af2 --- /dev/null +++ b/src/libs/clangbackendipc/highlightingmarkcontainer.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** 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 "highlightingmarkcontainer.h" + +#include <QDataStream> +#include <QDebug> + +#include <ostream> + +namespace ClangBackEnd { + +HighlightingMarkContainer::HighlightingMarkContainer(uint line, + uint column, + uint length, + HighlightingType type) + : line_(line), + column_(column), + length_(length), + type_(type) +{ +} + +uint HighlightingMarkContainer::line() const +{ + return line_; +} + +uint HighlightingMarkContainer::column() const +{ + return column_; +} + +uint HighlightingMarkContainer::length() const +{ + return length_; +} + +HighlightingType HighlightingMarkContainer::type() const +{ + return type_; +} + +quint32 &HighlightingMarkContainer::typeAsInt() +{ + return reinterpret_cast<quint32&>(type_); +} + +QDataStream &operator<<(QDataStream &out, const HighlightingMarkContainer &container) +{ + out << container.line_; + out << container.column_; + out << container.length_; + out << quint32(container.type_); + + return out; +} + +QDataStream &operator>>(QDataStream &in, HighlightingMarkContainer &container) +{ + in >> container.line_; + in >> container.column_; + in >> container.length_; + in >> container.typeAsInt(); + + return in; +} + +bool operator==(const HighlightingMarkContainer &first, const HighlightingMarkContainer &second) +{ + return first.line_ == second.line_ + && first.column_ == second.column_ + && first.length_ == second.length_ + && first.type_ == second.type_; +} + +bool operator<(const HighlightingMarkContainer &first, const HighlightingMarkContainer &second) +{ + if (first.line() == second.line()) { + if (first.column() == second.column()) { + if (first.length() == second.length()) + return first.type() < second.type(); + return first.length() < second.length(); + } + + return first.column() < second.column(); + } + + return first.line() < second.line(); +} + +#define RETURN_TEXT_FOR_CASE(enumValue) case HighlightingType::enumValue: return #enumValue +static const char *highlightingTypeToCStringLiteral(HighlightingType type) +{ + switch (type) { + RETURN_TEXT_FOR_CASE(Invalid); + RETURN_TEXT_FOR_CASE(Comment); + RETURN_TEXT_FOR_CASE(Keyword); + RETURN_TEXT_FOR_CASE(StringLiteral); + RETURN_TEXT_FOR_CASE(NumberLiteral); + RETURN_TEXT_FOR_CASE(Function); + RETURN_TEXT_FOR_CASE(VirtualFunction); + RETURN_TEXT_FOR_CASE(Type); + RETURN_TEXT_FOR_CASE(LocalVariable); + RETURN_TEXT_FOR_CASE(GlobalVariable); + RETURN_TEXT_FOR_CASE(Field); + RETURN_TEXT_FOR_CASE(Enumeration); + RETURN_TEXT_FOR_CASE(Operator); + RETURN_TEXT_FOR_CASE(Preprocessor); + RETURN_TEXT_FOR_CASE(Label); + RETURN_TEXT_FOR_CASE(OutputArgument); + RETURN_TEXT_FOR_CASE(PreprocessorDefinition); + RETURN_TEXT_FOR_CASE(PreprocessorExpansion); + default: return "UnhandledHighlightingType"; + } +} +#undef RETURN_TEXT_FOR_CASE + +QDebug operator<<(QDebug debug, const HighlightingMarkContainer &container) +{ + debug.nospace() << "HighlightingMarkContainer(" + << container.line() << ", " + << container.column() << ", " + << container.length() << ", " + << highlightingTypeToCStringLiteral(container.type()) << ", " + << ")"; + + return debug; +} + +void PrintTo(HighlightingType highlightingType, std::ostream *os) +{ + *os << highlightingTypeToCStringLiteral(highlightingType); +} + +void PrintTo(const HighlightingMarkContainer& container, ::std::ostream *os) +{ + *os << "HighlightingMarkContainer(" + << container.line() << ", " + << container.column() << ", " + << container.length() << ", "; + PrintTo(container.type(), os); + *os << ")"; +} + +} // namespace ClangBackEnd diff --git a/src/libs/clangbackendipc/highlightingmarkcontainer.h b/src/libs/clangbackendipc/highlightingmarkcontainer.h new file mode 100644 index 0000000000..e466cb868e --- /dev/null +++ b/src/libs/clangbackendipc/highlightingmarkcontainer.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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 CLANGBACKEND_HIGHLIGHTINGMARKCONTAINER_H +#define CLANGBACKEND_HIGHLIGHTINGMARKCONTAINER_H + +#include "clangbackendipc_global.h" + +#include <QMetaType> + +namespace ClangBackEnd { + +class CMBIPC_EXPORT HighlightingMarkContainer +{ + friend CMBIPC_EXPORT QDataStream &operator<<(QDataStream &out, const HighlightingMarkContainer &container); + friend CMBIPC_EXPORT QDataStream &operator>>(QDataStream &in, HighlightingMarkContainer &container); + friend CMBIPC_EXPORT bool operator==(const HighlightingMarkContainer &first, const HighlightingMarkContainer &second); + friend CMBIPC_EXPORT bool operator<(const HighlightingMarkContainer &first, const HighlightingMarkContainer &second); + +public: + HighlightingMarkContainer() = default; + HighlightingMarkContainer(uint line, uint column, uint length, HighlightingType type); + + uint line() const; + uint column() const; + uint length() const; + HighlightingType type() const; + +private: + quint32 &typeAsInt(); + +private: + uint line_; + uint column_; + uint length_; + HighlightingType type_; +}; + +CMBIPC_EXPORT QDataStream &operator<<(QDataStream &out, const HighlightingMarkContainer &container); +CMBIPC_EXPORT QDataStream &operator>>(QDataStream &in, HighlightingMarkContainer &container); +CMBIPC_EXPORT bool operator==(const HighlightingMarkContainer &first, const HighlightingMarkContainer &second); +CMBIPC_EXPORT bool operator<(const HighlightingMarkContainer &first, const HighlightingMarkContainer &second); + +CMBIPC_EXPORT QDebug operator<<(QDebug debug, const HighlightingMarkContainer &container); +CMBIPC_EXPORT void PrintTo(HighlightingType highlightingType, ::std::ostream *os); +void PrintTo(const HighlightingMarkContainer &container, ::std::ostream *os); + +} // namespace ClangBackEnd + +Q_DECLARE_METATYPE(ClangBackEnd::HighlightingMarkContainer) + +#endif // CLANGBACKEND_HIGHLIGHTINGMARKCONTAINER_H diff --git a/src/libs/clangbackendipc/ipcclientdispatcher.cpp b/src/libs/clangbackendipc/ipcclientdispatcher.cpp index bd9c7eb7f2..6b22a29f4a 100644 --- a/src/libs/clangbackendipc/ipcclientdispatcher.cpp +++ b/src/libs/clangbackendipc/ipcclientdispatcher.cpp @@ -80,5 +80,11 @@ void IpcClientDispatcher::diagnosticsChanged(const DiagnosticsChangedMessage &me client->diagnosticsChanged(message); } +void IpcClientDispatcher::highlightingChanged(const HighlightingChangedMessage &message) +{ + for (auto *client : clients) + client->highlightingChanged(message); +} + } // namespace ClangBackEnd diff --git a/src/libs/clangbackendipc/ipcclientdispatcher.h b/src/libs/clangbackendipc/ipcclientdispatcher.h index 7d8329e416..e8445df1f0 100644 --- a/src/libs/clangbackendipc/ipcclientdispatcher.h +++ b/src/libs/clangbackendipc/ipcclientdispatcher.h @@ -49,6 +49,7 @@ public: void translationUnitDoesNotExist(const TranslationUnitDoesNotExistMessage &message) override; void projectPartsDoNotExist(const ProjectPartsDoNotExistMessage &message) override; void diagnosticsChanged(const DiagnosticsChangedMessage &message) override; + void highlightingChanged(const HighlightingChangedMessage &message) override; private: QVector<IpcClientInterface*> clients; diff --git a/src/libs/clangbackendipc/ipcclientinterface.cpp b/src/libs/clangbackendipc/ipcclientinterface.cpp index 28d2410662..b6447949e6 100644 --- a/src/libs/clangbackendipc/ipcclientinterface.cpp +++ b/src/libs/clangbackendipc/ipcclientinterface.cpp @@ -35,6 +35,7 @@ #include "projectpartsdonotexistmessage.h" #include "translationunitdoesnotexistmessage.h" #include "diagnosticschangedmessage.h" +#include "highlightingchangedmessage.h" #include <QDebug> #include <QVariant> @@ -50,6 +51,7 @@ void IpcClientInterface::dispatch(const QVariant &message) static const int translationUnitDoesNotExistMessage = QMetaType::type("ClangBackEnd::TranslationUnitDoesNotExistMessage"); static const int projectPartsDoNotExistMessage = QMetaType::type("ClangBackEnd::ProjectPartsDoNotExistMessage"); static const int diagnosticsChangedMessage = QMetaType::type("ClangBackEnd::DiagnosticsChangedMessage"); + static const int highlightingChangedMessage = QMetaType::type("ClangBackEnd::HighlightingChangedMessage"); int type = message.userType(); @@ -65,6 +67,8 @@ void IpcClientInterface::dispatch(const QVariant &message) projectPartsDoNotExist(message.value<ProjectPartsDoNotExistMessage>()); else if (type == diagnosticsChangedMessage) diagnosticsChanged(message.value<DiagnosticsChangedMessage>()); + else if (type == highlightingChangedMessage) + highlightingChanged(message.value<HighlightingChangedMessage>()); else qWarning() << "Unknown IpcClientMessage"; } diff --git a/src/libs/clangbackendipc/ipcclientinterface.h b/src/libs/clangbackendipc/ipcclientinterface.h index 5600e13076..539371e12d 100644 --- a/src/libs/clangbackendipc/ipcclientinterface.h +++ b/src/libs/clangbackendipc/ipcclientinterface.h @@ -51,6 +51,8 @@ class RequestDiagnosticsMessage; class RegisterUnsavedFilesForEditorMessage; class UnregisterUnsavedFilesForEditorMessage; class UpdateVisibleTranslationUnitsMessage; +class RequestHighlightingMessage; +class HighlightingChangedMessage; class CMBIPC_EXPORT IpcClientInterface : public IpcInterface { @@ -63,6 +65,7 @@ public: virtual void translationUnitDoesNotExist(const TranslationUnitDoesNotExistMessage &message) = 0; virtual void projectPartsDoNotExist(const ProjectPartsDoNotExistMessage &message) = 0; virtual void diagnosticsChanged(const DiagnosticsChangedMessage &message) = 0; + virtual void highlightingChanged(const HighlightingChangedMessage &message) = 0; }; } // namespace ClangBackEnd diff --git a/src/libs/clangbackendipc/ipcclientproxy.cpp b/src/libs/clangbackendipc/ipcclientproxy.cpp index cb058b7bb4..cbfddf8522 100644 --- a/src/libs/clangbackendipc/ipcclientproxy.cpp +++ b/src/libs/clangbackendipc/ipcclientproxy.cpp @@ -35,6 +35,7 @@ #include "cmbechomessage.h" #include "cmbregistertranslationunitsforeditormessage.h" #include "diagnosticschangedmessage.h" +#include "highlightingchangedmessage.h" #include "ipcserverinterface.h" #include "projectpartsdonotexistmessage.h" #include "translationunitdoesnotexistmessage.h" @@ -104,6 +105,11 @@ void IpcClientProxy::diagnosticsChanged(const DiagnosticsChangedMessage &message writeMessageBlock.write(QVariant::fromValue(message)); } +void IpcClientProxy::highlightingChanged(const HighlightingChangedMessage &message) +{ + writeMessageBlock.write(QVariant::fromValue(message)); +} + void IpcClientProxy::readMessages() { for (const QVariant &message : readMessageBlock.readAll()) diff --git a/src/libs/clangbackendipc/ipcclientproxy.h b/src/libs/clangbackendipc/ipcclientproxy.h index 77b53c7cd2..d239631b9a 100644 --- a/src/libs/clangbackendipc/ipcclientproxy.h +++ b/src/libs/clangbackendipc/ipcclientproxy.h @@ -63,6 +63,7 @@ public: void translationUnitDoesNotExist(const TranslationUnitDoesNotExistMessage &message) override; void projectPartsDoNotExist(const ProjectPartsDoNotExistMessage &message) override; void diagnosticsChanged(const DiagnosticsChangedMessage &message) override; + void highlightingChanged(const HighlightingChangedMessage &message) override; void readMessages(); diff --git a/src/libs/clangbackendipc/ipcserverinterface.cpp b/src/libs/clangbackendipc/ipcserverinterface.cpp index 93717dfa33..d25fee4525 100644 --- a/src/libs/clangbackendipc/ipcserverinterface.cpp +++ b/src/libs/clangbackendipc/ipcserverinterface.cpp @@ -37,6 +37,7 @@ #include "cmbunregistertranslationunitsforeditormessage.h" #include "registerunsavedfilesforeditormessage.h" #include "requestdiagnosticsmessage.h" +#include "requesthighlightingmessage.h" #include "unregisterunsavedfilesforeditormessage.h" #include "updatetranslationunitsforeditormessage.h" #include "updatevisibletranslationunitsmessage.h" @@ -58,9 +59,9 @@ void IpcServerInterface::dispatch(const QVariant &message) static const int unregisterUnsavedFilesForEditorMessageType = QMetaType::type("ClangBackEnd::UnregisterUnsavedFilesForEditorMessage"); static const int completeCodeMessageType = QMetaType::type("ClangBackEnd::CompleteCodeMessage"); static const int requestDiagnosticsMessageType = QMetaType::type("ClangBackEnd::RequestDiagnosticsMessage"); + static const int requestHighlightingTypeMessage = QMetaType::type("ClangBackEnd::RequestHighlightingMessage"); static const int updateVisibleTranslationUnitsMessageType = QMetaType::type("ClangBackEnd::UpdateVisibleTranslationUnitsMessage"); - int type = message.userType(); if (type == endMessageType) @@ -83,6 +84,8 @@ void IpcServerInterface::dispatch(const QVariant &message) completeCode(message.value<CompleteCodeMessage>()); else if (type == requestDiagnosticsMessageType) requestDiagnostics(message.value<RequestDiagnosticsMessage>()); + else if (type == requestHighlightingTypeMessage) + requestHighlighting(message.value<RequestHighlightingMessage>()); else if (type == updateVisibleTranslationUnitsMessageType) updateVisibleTranslationUnits(message.value<UpdateVisibleTranslationUnitsMessage>()); else diff --git a/src/libs/clangbackendipc/ipcserverinterface.h b/src/libs/clangbackendipc/ipcserverinterface.h index 98d1441c0d..451bcaab75 100644 --- a/src/libs/clangbackendipc/ipcserverinterface.h +++ b/src/libs/clangbackendipc/ipcserverinterface.h @@ -54,6 +54,7 @@ public: virtual void unregisterUnsavedFilesForEditor(const UnregisterUnsavedFilesForEditorMessage &message) = 0; virtual void completeCode(const CompleteCodeMessage &message) = 0; virtual void requestDiagnostics(const RequestDiagnosticsMessage &message) = 0; + virtual void requestHighlighting(const RequestHighlightingMessage &message) = 0; virtual void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) = 0; void addClient(IpcClientInterface *client); diff --git a/src/libs/clangbackendipc/ipcserverproxy.cpp b/src/libs/clangbackendipc/ipcserverproxy.cpp index fa5777267c..90419da958 100644 --- a/src/libs/clangbackendipc/ipcserverproxy.cpp +++ b/src/libs/clangbackendipc/ipcserverproxy.cpp @@ -40,6 +40,7 @@ #include <ipcclientinterface.h> #include <registerunsavedfilesforeditormessage.h> #include <requestdiagnosticsmessage.h> +#include <requesthighlightingmessage.h> #include <unregisterunsavedfilesforeditormessage.h> #include <updatetranslationunitsforeditormessage.h> #include <updatevisibletranslationunitsmessage.h> @@ -120,6 +121,11 @@ void IpcServerProxy::requestDiagnostics(const ClangBackEnd::RequestDiagnosticsMe writeMessageBlock.write(QVariant::fromValue(message)); } +void IpcServerProxy::requestHighlighting(const RequestHighlightingMessage &message) +{ + writeMessageBlock.write(QVariant::fromValue(message)); +} + void IpcServerProxy::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) { writeMessageBlock.write(QVariant::fromValue(message)); diff --git a/src/libs/clangbackendipc/ipcserverproxy.h b/src/libs/clangbackendipc/ipcserverproxy.h index d4c42887f4..6d6db7e4f2 100644 --- a/src/libs/clangbackendipc/ipcserverproxy.h +++ b/src/libs/clangbackendipc/ipcserverproxy.h @@ -65,7 +65,9 @@ public: void unregisterUnsavedFilesForEditor(const UnregisterUnsavedFilesForEditorMessage &message) override; void completeCode(const CompleteCodeMessage &message) override; void requestDiagnostics(const RequestDiagnosticsMessage &message) override; + void requestHighlighting(const RequestHighlightingMessage &message) override; void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override; + void readMessages(); void resetCounter(); diff --git a/src/plugins/clangcodemodel/symbol.h b/src/libs/clangbackendipc/requesthighlightingmessage.cpp index 9dafa0cd7b..8dcc105e1f 100644 --- a/src/plugins/clangcodemodel/symbol.h +++ b/src/libs/clangbackendipc/requesthighlightingmessage.cpp @@ -28,51 +28,62 @@ ** ****************************************************************************/ -#ifndef INDEXEDSYMBOLINFO_H -#define INDEXEDSYMBOLINFO_H +#include "requesthighlightingmessage.h" -#include "sourcelocation.h" - -#include <QString> #include <QDataStream> -#include <QIcon> +#include <QDebug> + +#include <ostream> + +namespace ClangBackEnd { + +RequestHighlightingMessage::RequestHighlightingMessage(const FileContainer &file) + : fileContainer_(file) +{ +} + +const FileContainer RequestHighlightingMessage::fileContainer() const +{ + return fileContainer_; +} + +QDataStream &operator<<(QDataStream &out, const RequestHighlightingMessage &message) +{ + out << message.fileContainer_; + + return out; +} -namespace ClangCodeModel { +QDataStream &operator>>(QDataStream &in, RequestHighlightingMessage &message) +{ + in >> message.fileContainer_; + + return in; +} + +bool operator==(const RequestHighlightingMessage &first, const RequestHighlightingMessage &second) +{ + return first.fileContainer_ == second.fileContainer_; +} + +bool operator<(const RequestHighlightingMessage &first, const RequestHighlightingMessage &second) +{ + return first.fileContainer_ < second.fileContainer_; +} -class Symbol +QDebug operator<<(QDebug debug, const RequestHighlightingMessage &message) { -public: - enum Kind { - Enum, - Class, - Method, // A member-function. - Function, // A free-function (global or within a namespace). - Declaration, - Constructor, - Destructor, - Unknown - }; - - Symbol(); - Symbol(const QString &name, - const QString &qualification, - Kind type, - const SourceLocation &location); - - QString m_name; - QString m_qualification; - SourceLocation m_location; - Kind m_kind; - - QIcon iconForSymbol() const; -}; - -QDataStream &operator<<(QDataStream &stream, const Symbol &symbol); -QDataStream &operator>>(QDataStream &stream, Symbol &symbol); - -bool operator==(const Symbol &a, const Symbol &b); -bool operator!=(const Symbol &a, const Symbol &b); - -} // Clang - -#endif // INDEXEDSYMBOLINFO_H + debug.nospace() << "RequestHighlightingMessage(" + << message.fileContainer() + << ")"; + + return debug; +} + +void PrintTo(const RequestHighlightingMessage &message, ::std::ostream* os) +{ + *os << message.fileContainer().filePath().constData() + << "(" << message.fileContainer().projectPartId().constData() << ")"; +} + +} // namespace ClangBackEnd diff --git a/src/libs/clangbackendipc/requesthighlightingmessage.h b/src/libs/clangbackendipc/requesthighlightingmessage.h new file mode 100644 index 0000000000..ff611d5216 --- /dev/null +++ b/src/libs/clangbackendipc/requesthighlightingmessage.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** 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 CLANGBACKEND_REQUESTHIGHLIGHTING_H +#define CLANGBACKEND_REQUESTHIGHLIGHTING_H + +#include "filecontainer.h" + +namespace ClangBackEnd { + +class CMBIPC_EXPORT RequestHighlightingMessage +{ + friend CMBIPC_EXPORT QDataStream &operator<<(QDataStream &out, const RequestHighlightingMessage &message); + friend CMBIPC_EXPORT QDataStream &operator>>(QDataStream &in, RequestHighlightingMessage &message); + friend CMBIPC_EXPORT bool operator==(const RequestHighlightingMessage &first, const RequestHighlightingMessage &second); + friend CMBIPC_EXPORT bool operator<(const RequestHighlightingMessage &first, const RequestHighlightingMessage &second); + friend CMBIPC_EXPORT QDebug operator<<(QDebug debug, const RequestHighlightingMessage &message); + friend void PrintTo(const RequestHighlightingMessage &message, ::std::ostream* os); + +public: + RequestHighlightingMessage() = default; + RequestHighlightingMessage(const FileContainer &fileContainer); + + const FileContainer fileContainer() const; + +private: + FileContainer fileContainer_; +}; + +CMBIPC_EXPORT QDataStream &operator<<(QDataStream &out, const RequestHighlightingMessage &message); +CMBIPC_EXPORT QDataStream &operator>>(QDataStream &in, RequestHighlightingMessage &message); +CMBIPC_EXPORT bool operator==(const RequestHighlightingMessage &first, const RequestHighlightingMessage &second); +CMBIPC_EXPORT bool operator<(const RequestHighlightingMessage &first, const RequestHighlightingMessage &second); + +CMBIPC_EXPORT QDebug operator<<(QDebug debug, const RequestHighlightingMessage &message); +void PrintTo(const RequestHighlightingMessage &message, ::std::ostream* os); + +} // namespace ClangBackEnd + +Q_DECLARE_METATYPE(ClangBackEnd::RequestHighlightingMessage) + +#endif // CLANGBACKEND_REQUESTHIGHLIGHTING_H diff --git a/src/libs/cplusplus/MatchingText.h b/src/libs/cplusplus/MatchingText.h index bf4738f857..6c041defdf 100644 --- a/src/libs/cplusplus/MatchingText.h +++ b/src/libs/cplusplus/MatchingText.h @@ -31,6 +31,7 @@ #ifndef CPLUSPLUS_MATCHINGTEXT_H #define CPLUSPLUS_MATCHINGTEXT_H +#include <QtGlobal> #include <cplusplus/CPlusPlusForwardDeclarations.h> QT_FORWARD_DECLARE_CLASS(QTextCursor) diff --git a/src/libs/sqlite/sqlite.pro b/src/libs/sqlite/sqlite.pro index 741e6a6cbf..f3c75fa373 100644 --- a/src/libs/sqlite/sqlite.pro +++ b/src/libs/sqlite/sqlite.pro @@ -2,4 +2,8 @@ unix:QMAKE_CXXFLAGS_DEBUG += -O2 win32:QMAKE_CXXFLAGS_DEBUG += -O2 include(../../qtcreatorlibrary.pri) + +win32:DEFINES += SQLITE_API=__declspec(dllexport) +unix:DEFINES += SQLITE_API=\"__attribute__((visibility(\\\"default\\\")))\" + include(sqlite-lib.pri) diff --git a/src/plugins/android/androidmanager.cpp b/src/plugins/android/androidmanager.cpp index 1882f6e91c..4a2c49bdca 100644 --- a/src/plugins/android/androidmanager.cpp +++ b/src/plugins/android/androidmanager.cpp @@ -280,7 +280,7 @@ QString AndroidManager::loadLocalJarsInitClasses(ProjectExplorer::Target *target QPair<int, int> AndroidManager::apiLevelRange() { - return qMakePair(9, 22); + return qMakePair(9, 23); } QString AndroidManager::androidNameForApiLevel(int x) @@ -324,6 +324,8 @@ QString AndroidManager::androidNameForApiLevel(int x) return QLatin1String("Android 5.0"); case 22: return QLatin1String("Android 5.1"); + case 23: + return QLatin1String("Android 6.0"); default: return tr("Unknown Android version. API Level: %1").arg(QString::number(x)); } diff --git a/src/plugins/bookmarks/bookmark.cpp b/src/plugins/bookmarks/bookmark.cpp index 70c0352d11..7951bf30cb 100644 --- a/src/plugins/bookmarks/bookmark.cpp +++ b/src/plugins/bookmarks/bookmark.cpp @@ -32,7 +32,6 @@ #include "bookmarkmanager.h" #include "bookmarks_global.h" -#include <QDebug> #include <QFileInfo> #include <QTextBlock> diff --git a/src/plugins/bookmarks/bookmarksplugin.cpp b/src/plugins/bookmarks/bookmarksplugin.cpp index a8014e8486..dc38b49c8b 100644 --- a/src/plugins/bookmarks/bookmarksplugin.cpp +++ b/src/plugins/bookmarks/bookmarksplugin.cpp @@ -46,7 +46,6 @@ #include <texteditor/texteditorconstants.h> #include <QtPlugin> -#include <QDebug> #include <QMenu> diff --git a/src/plugins/clangcodemodel/clang_global.h b/src/plugins/clangcodemodel/clang_global.h deleted file mode 100644 index 2f0faa7fc1..0000000000 --- a/src/plugins/clangcodemodel/clang_global.h +++ /dev/null @@ -1,43 +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_GLOBAL_H -#define CLANG_GLOBAL_H - -#include <qglobal.h> - -#if defined(CLANGCODEMODEL_LIBRARY) -# define CLANG_EXPORT Q_DECL_EXPORT -#else -# define CLANG_EXPORT Q_DECL_IMPORT -#endif - - -#endif // CLANG_GLOBAL_H diff --git a/src/plugins/clangcodemodel/activationsequencecontextprocessor.cpp b/src/plugins/clangcodemodel/clangactivationsequencecontextprocessor.cpp index 1b03f0e5b7..0b19ce24ae 100644 --- a/src/plugins/clangcodemodel/activationsequencecontextprocessor.cpp +++ b/src/plugins/clangcodemodel/clangactivationsequencecontextprocessor.cpp @@ -28,9 +28,9 @@ ** ****************************************************************************/ -#include "activationsequencecontextprocessor.h" +#include "clangactivationsequencecontextprocessor.h" -#include "activationsequenceprocessor.h" +#include "clangactivationsequenceprocessor.h" #include <cplusplus/BackwardsScanner.h> #include <cplusplus/ExpressionUnderCursor.h> diff --git a/src/plugins/clangcodemodel/activationsequencecontextprocessor.h b/src/plugins/clangcodemodel/clangactivationsequencecontextprocessor.h index f63bfa2c5a..f63bfa2c5a 100644 --- a/src/plugins/clangcodemodel/activationsequencecontextprocessor.h +++ b/src/plugins/clangcodemodel/clangactivationsequencecontextprocessor.h diff --git a/src/plugins/clangcodemodel/activationsequenceprocessor.cpp b/src/plugins/clangcodemodel/clangactivationsequenceprocessor.cpp index a7f4ea948d..08f97558e7 100644 --- a/src/plugins/clangcodemodel/activationsequenceprocessor.cpp +++ b/src/plugins/clangcodemodel/clangactivationsequenceprocessor.cpp @@ -28,7 +28,7 @@ ** ****************************************************************************/ -#include "activationsequenceprocessor.h" +#include "clangactivationsequenceprocessor.h" namespace ClangCodeModel { namespace Internal { diff --git a/src/plugins/clangcodemodel/activationsequenceprocessor.h b/src/plugins/clangcodemodel/clangactivationsequenceprocessor.h index 2c6350dbaf..2c6350dbaf 100644 --- a/src/plugins/clangcodemodel/activationsequenceprocessor.h +++ b/src/plugins/clangcodemodel/clangactivationsequenceprocessor.h diff --git a/src/plugins/clangcodemodel/clangassistproposal.cpp b/src/plugins/clangcodemodel/clangassistproposal.cpp index 4bb34a97c1..6904f9abfc 100644 --- a/src/plugins/clangcodemodel/clangassistproposal.cpp +++ b/src/plugins/clangcodemodel/clangassistproposal.cpp @@ -42,7 +42,7 @@ ClangAssistProposal::ClangAssistProposal(int cursorPos, TextEditor::GenericPropo bool ClangAssistProposal::isCorrective() const { - return ClangAssistProposalModel::replaceDotForArrow(model()); + return false; } void ClangAssistProposal::makeCorrection(TextEditor::TextEditorWidget *editorWidget) diff --git a/src/plugins/clangcodemodel/clangassistproposal.h b/src/plugins/clangcodemodel/clangassistproposal.h index 6a0ada3d79..198f739742 100644 --- a/src/plugins/clangcodemodel/clangassistproposal.h +++ b/src/plugins/clangcodemodel/clangassistproposal.h @@ -45,9 +45,6 @@ public: virtual bool isCorrective() const; virtual void makeCorrection(TextEditor::TextEditorWidget *editorWidget); - -private: - bool m_replaceDotForArrow; }; } // namespace Internal diff --git a/src/plugins/clangcodemodel/clangassistproposalitem.cpp b/src/plugins/clangcodemodel/clangassistproposalitem.cpp index f44a2a8b28..f96128b917 100644 --- a/src/plugins/clangcodemodel/clangassistproposalitem.cpp +++ b/src/plugins/clangcodemodel/clangassistproposalitem.cpp @@ -30,7 +30,7 @@ #include "clangassistproposalitem.h" -#include "completionchunkstotextconverter.h" +#include "clangcompletionchunkstotextconverter.h" #include <cplusplus/MatchingText.h> #include <cplusplus/Token.h> diff --git a/src/plugins/clangcodemodel/clangassistproposalmodel.cpp b/src/plugins/clangcodemodel/clangassistproposalmodel.cpp index b07b2eb42e..d4085b3929 100644 --- a/src/plugins/clangcodemodel/clangassistproposalmodel.cpp +++ b/src/plugins/clangcodemodel/clangassistproposalmodel.cpp @@ -39,13 +39,6 @@ namespace ClangCodeModel { namespace Internal { -bool ClangAssistProposalModel::replaceDotForArrow(TextEditor::IAssistProposalModel *model) -{ - auto clangAssistProposalModel = static_cast<ClangAssistProposalModel*>(model); - - return clangAssistProposalModel->m_replaceDotForArrow; -} - bool ClangAssistProposalModel::isSortable(const QString &/*prefix*/) const { return true; diff --git a/src/plugins/clangcodemodel/clangassistproposalmodel.h b/src/plugins/clangcodemodel/clangassistproposalmodel.h index 408ee990eb..5f7b1f502a 100644 --- a/src/plugins/clangcodemodel/clangassistproposalmodel.h +++ b/src/plugins/clangcodemodel/clangassistproposalmodel.h @@ -41,21 +41,8 @@ namespace Internal { class ClangAssistProposalModel : public TextEditor::GenericProposalModel { public: - ClangAssistProposalModel() - : m_sortable(false) - , m_completionOperator(CPlusPlus::T_EOF_SYMBOL) - , m_replaceDotForArrow(false) - {} - bool isSortable(const QString &prefix) const override; void sort(const QString &prefix) override; - - static bool replaceDotForArrow(IAssistProposalModel *model); - -private: - bool m_sortable; - unsigned m_completionOperator; - bool m_replaceDotForArrow; }; } // namespace Internal diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp index 24c3415b0f..0e664aee80 100644 --- a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp +++ b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp @@ -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> @@ -48,6 +47,7 @@ #include <texteditor/texteditor.h> #include <clangbackendipc/diagnosticschangedmessage.h> +#include <clangbackendipc/highlightingchangedmessage.h> #include <utils/hostosinfo.h> #include <utils/qtcassert.h> @@ -62,11 +62,13 @@ #include <clangbackendipc/cmbmessages.h> #include <clangbackendipc/registerunsavedfilesforeditormessage.h> #include <clangbackendipc/requestdiagnosticsmessage.h> +#include <clangbackendipc/requesthighlightingmessage.h> #include <clangbackendipc/filecontainer.h> #include <clangbackendipc/projectpartsdonotexistmessage.h> #include <clangbackendipc/translationunitdoesnotexistmessage.h> #include <clangbackendipc/unregisterunsavedfilesforeditormessage.h> #include <clangbackendipc/updatetranslationunitsforeditormessage.h> +#include <clangbackendipc/updatevisibletranslationunitsmessage.h> #include <cplusplus/Icons.h> @@ -135,6 +137,11 @@ void IpcReceiver::deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidget *t } } +bool IpcReceiver::isExpectingCodeCompletedMessage() const +{ + return !m_assistProcessorsTable.isEmpty(); +} + void IpcReceiver::alive() { qCDebug(log) << "<<< AliveMessage"; @@ -174,6 +181,24 @@ void IpcReceiver::diagnosticsChanged(const DiagnosticsChangedMessage &message) } } +void IpcReceiver::highlightingChanged(const HighlightingChangedMessage &message) +{ + qCDebug(log) << "<<< HighlightingChangedMessage with" + << message.highlightingMarks().size() << "items"; + + auto processor = ClangEditorDocumentProcessor::get(message.file().filePath()); + + if (processor && processor->projectPart()) { + const QString highlightingProjectPartId = message.file().projectPartId(); + const QString documentProjectPartId = processor->projectPart()->id(); + if (highlightingProjectPartId == documentProjectPartId) { + processor->updateHighlighting(message.highlightingMarks(), + message.skippedPreprocessorRanges(), + message.file().documentRevision()); + } + } +} + void IpcReceiver::translationUnitDoesNotExist(const TranslationUnitDoesNotExistMessage &message) { QTC_CHECK(!"Got TranslationUnitDoesNotExistMessage"); @@ -203,6 +228,8 @@ public: void unregisterUnsavedFilesForEditor(const ClangBackEnd::UnregisterUnsavedFilesForEditorMessage &message) override; void completeCode(const ClangBackEnd::CompleteCodeMessage &message) override; void requestDiagnostics(const ClangBackEnd::RequestDiagnosticsMessage &message) override; + void requestHighlighting(const ClangBackEnd::RequestHighlightingMessage &message) override; + void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override; private: ClangBackEnd::ConnectionClient &m_connection; @@ -268,6 +295,18 @@ void IpcSender::requestDiagnostics(const RequestDiagnosticsMessage &message) m_connection.serverProxy().requestDiagnostics(message); } +void IpcSender::requestHighlighting(const RequestHighlightingMessage &message) +{ + QTC_CHECK(m_connection.isConnected()); + m_connection.serverProxy().requestHighlighting(message); +} + +void IpcSender::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) +{ + QTC_CHECK(m_connection.isConnected()); + m_connection.serverProxy().updateVisibleTranslationUnits(message); +} + IpcCommunicator::IpcCommunicator() : m_connection(&m_ipcReceiver) , m_ipcSender(new IpcSender(m_connection)) @@ -308,10 +347,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; } @@ -346,6 +383,90 @@ void IpcCommunicator::registerFallbackProjectPart() registerProjectPartsForEditor({projectPartContainer}); } +namespace { +Utf8String currentCppEditorDocumentFilePath() +{ + Utf8String currentCppEditorDocumentFilePath; + + const auto currentEditor = Core::EditorManager::currentEditor(); + if (currentEditor && CppTools::CppModelManager::isCppEditor(currentEditor)) { + const auto currentDocument = currentEditor->document(); + if (currentDocument) + currentCppEditorDocumentFilePath = currentDocument->filePath().toString(); + } + + return currentCppEditorDocumentFilePath; +} + +void removeDuplicates(Utf8StringVector &visibleEditorDocumentsFilePaths) +{ + std::sort(visibleEditorDocumentsFilePaths.begin(), + visibleEditorDocumentsFilePaths.end()); + const auto end = std::unique(visibleEditorDocumentsFilePaths.begin(), + visibleEditorDocumentsFilePaths.end()); + visibleEditorDocumentsFilePaths.erase(end, + visibleEditorDocumentsFilePaths.end()); +} + +void removeNonCppEditors(QList<Core::IEditor*> &visibleEditors) +{ + const auto isNotCppEditor = [] (Core::IEditor *editor) { + return !CppTools::CppModelManager::isCppEditor(editor); + }; + + const auto end = std::remove_if(visibleEditors.begin(), + visibleEditors.end(), + isNotCppEditor); + + visibleEditors.erase(end, visibleEditors.end()); +} + +Utf8StringVector visibleCppEditorDocumentsFilePaths() +{ + auto visibleEditors = Core::EditorManager::visibleEditors(); + + removeNonCppEditors(visibleEditors); + + Utf8StringVector visibleCppEditorDocumentsFilePaths; + visibleCppEditorDocumentsFilePaths.reserve(visibleEditors.size()); + + const auto editorFilePaths = [] (Core::IEditor *editor) { + return Utf8String(editor->document()->filePath().toString()); + }; + + std::transform(visibleEditors.begin(), + visibleEditors.end(), + std::back_inserter(visibleCppEditorDocumentsFilePaths), + editorFilePaths); + + removeDuplicates(visibleCppEditorDocumentsFilePaths); + + return visibleCppEditorDocumentsFilePaths; +} + +} + +void IpcCommunicator::updateTranslationUnitVisiblity() +{ + updateTranslationUnitVisiblity(currentCppEditorDocumentFilePath(), visibleCppEditorDocumentsFilePaths()); +} + +bool IpcCommunicator::isNotWaitingForCompletion() const +{ + return !m_ipcReceiver.isExpectingCodeCompletedMessage(); +} + +void IpcCommunicator::updateTranslationUnitVisiblity(const Utf8String ¤tEditorFilePath, + const Utf8StringVector &visibleEditorsFilePaths) +{ + if (m_sendMode == IgnoreSendRequests) + return; + + const UpdateVisibleTranslationUnitsMessage message(currentEditorFilePath, visibleEditorsFilePaths); + qCDebug(log) << ">>>" << message; + m_ipcSender->updateVisibleTranslationUnits(message); +} + void IpcCommunicator::registerCurrentProjectParts() { using namespace CppTools; @@ -355,15 +476,24 @@ void IpcCommunicator::registerCurrentProjectParts() registerProjectsParts(projectInfo.projectParts()); } -void IpcCommunicator::registerCurrentCppEditorDocuments() +void IpcCommunicator::restoreCppEditorDocuments() +{ + resetCppEditorDocumentProcessors(); + registerVisibleCppEditorDocumentAndMarkInvisibleDirty(); +} + +void IpcCommunicator::resetCppEditorDocumentProcessors() { using namespace CppTools; const auto cppEditorDocuments = CppModelManager::instance()->cppEditorDocuments(); - foreach (const CppEditorDocumentHandle *cppEditorDocument, cppEditorDocuments) { - if (cppEditorDocument->processor()->baseTextDocument()->isModified()) - updateTranslationUnitFromCppEditorDocument(cppEditorDocument->filePath()); - } + foreach (CppEditorDocumentHandle *cppEditorDocument, cppEditorDocuments) + cppEditorDocument->resetProcessor(); +} + +void IpcCommunicator::registerVisibleCppEditorDocumentAndMarkInvisibleDirty() +{ + CppTools::CppModelManager::instance()->updateCppEditorDocuments(); } void IpcCommunicator::registerCurrentCodeModelUiHeaders() @@ -401,12 +531,13 @@ CppTools::CppEditorDocumentHandle *cppDocument(const QString &filePath) return CppTools::CppModelManager::instance()->cppEditorDocument(filePath); } -bool documentHasChanged(const QString &filePath) +bool documentHasChanged(const QString &filePath, + uint revision) { auto *document = cppDocument(filePath); if (document) - return document->sendTracker().shouldSendRevision(document->revision()); + return document->sendTracker().shouldSendRevision(revision); return true; } @@ -446,33 +577,42 @@ void IpcCommunicator::updateUnsavedFile(const QString &filePath, const QByteArra documentRevision}}); } -void IpcCommunicator::requestDiagnostics(const FileContainer &fileContainer) +void IpcCommunicator::updateTranslationUnitWithRevisionCheck(const FileContainer &fileContainer) { if (m_sendMode == IgnoreSendRequests) return; - if (documentHasChanged(fileContainer.filePath())) { + if (documentHasChanged(fileContainer.filePath(), fileContainer.documentRevision())) { updateTranslationUnitsForEditor({fileContainer}); - - const RequestDiagnosticsMessage message(fileContainer); - qCDebug(log) << ">>>" << message; - m_ipcSender->requestDiagnostics(message); - setLastSentDocumentRevision(fileContainer.filePath(), fileContainer.documentRevision()); } } -void IpcCommunicator::requestDiagnostics(Core::IDocument *document) +void IpcCommunicator::requestDiagnostics(const FileContainer &fileContainer) +{ + const RequestDiagnosticsMessage message(fileContainer); + qCDebug(log) << ">>>" << message; + m_ipcSender->requestDiagnostics(message); +} + +void IpcCommunicator::requestHighlighting(const FileContainer &fileContainer) +{ + const RequestHighlightingMessage message(fileContainer); + qCDebug(log) << ">>>" << message; + m_ipcSender->requestHighlighting(message); +} + +void IpcCommunicator::updateTranslationUnitWithRevisionCheck(Core::IDocument *document) { const auto textDocument = qobject_cast<TextDocument*>(document); const auto filePath = textDocument->filePath().toString(); const QString projectPartId = Utils::projectPartIdForFile(filePath); - requestDiagnostics(FileContainer(filePath, - projectPartId, - Utf8StringVector(), - textDocument->document()->revision())); + updateTranslationUnitWithRevisionCheck(FileContainer(filePath, + projectPartId, + Utf8StringVector(), + textDocument->document()->revision())); } void IpcCommunicator::updateChangeContentStartPosition(const QString &filePath, int position) @@ -526,8 +666,9 @@ void IpcCommunicator::initializeBackendWithCurrentData() { registerFallbackProjectPart(); registerCurrentProjectParts(); - registerCurrentCppEditorDocuments(); registerCurrentCodeModelUiHeaders(); + restoreCppEditorDocuments(); + updateTranslationUnitVisiblity(); emit backendReinitialized(); } @@ -549,7 +690,9 @@ void IpcCommunicator::registerTranslationUnitsForEditor(const FileContainers &fi if (m_sendMode == IgnoreSendRequests) return; - const RegisterTranslationUnitForEditorMessage message(fileContainers); + const RegisterTranslationUnitForEditorMessage message(fileContainers, + currentCppEditorDocumentFilePath(), + visibleCppEditorDocumentsFilePaths()); qCDebug(log) << ">>>" << message; m_ipcSender->registerTranslationUnitsForEditor(message); } diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.h b/src/plugins/clangcodemodel/clangbackendipcintegration.h index 030976bfbe..3d6a299c51 100644 --- a/src/plugins/clangcodemodel/clangbackendipcintegration.h +++ b/src/plugins/clangcodemodel/clangbackendipcintegration.h @@ -76,11 +76,14 @@ public: void deleteAndClearWaitingAssistProcessors(); void deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidget *textEditorWidget); + bool isExpectingCodeCompletedMessage() const; + private: void alive() override; void echo(const ClangBackEnd::EchoMessage &message) override; void codeCompleted(const ClangBackEnd::CodeCompletedMessage &message) override; void diagnosticsChanged(const ClangBackEnd::DiagnosticsChangedMessage &message) override; + void highlightingChanged(const ClangBackEnd::HighlightingChangedMessage &message) override; void translationUnitDoesNotExist(const ClangBackEnd::TranslationUnitDoesNotExistMessage &message) override; void projectPartsDoNotExist(const ClangBackEnd::ProjectPartsDoNotExistMessage &message) override; @@ -105,6 +108,8 @@ public: virtual void unregisterUnsavedFilesForEditor(const ClangBackEnd::UnregisterUnsavedFilesForEditorMessage &message) = 0; virtual void completeCode(const ClangBackEnd::CompleteCodeMessage &message) = 0; virtual void requestDiagnostics(const ClangBackEnd::RequestDiagnosticsMessage &message) = 0; + virtual void requestHighlighting(const ClangBackEnd::RequestHighlightingMessage &message) = 0; + virtual void updateVisibleTranslationUnits(const ClangBackEnd::UpdateVisibleTranslationUnitsMessage &message) = 0; }; class IpcCommunicator : public QObject @@ -126,6 +131,8 @@ public: void unregisterProjectPartsForEditor(const QStringList &projectPartIds); void registerUnsavedFilesForEditor(const FileContainers &fileContainers); void unregisterUnsavedFilesForEditor(const FileContainers &fileContainers); + void requestDiagnostics(const ClangBackEnd::FileContainer &fileContainer); + void requestHighlighting(const ClangBackEnd::FileContainer &fileContainer); void completeCode(ClangCompletionAssistProcessor *assistProcessor, const QString &filePath, quint32 line, quint32 column, @@ -140,11 +147,14 @@ public: void updateUnsavedFileFromCppEditorDocument(const QString &filePath); void updateTranslationUnit(const QString &filePath, const QByteArray &contents, uint documentRevision); void updateUnsavedFile(const QString &filePath, const QByteArray &contents, uint documentRevision); - void requestDiagnostics(const ClangBackEnd::FileContainer &fileContainer); - void requestDiagnostics(Core::IDocument *document); + void updateTranslationUnitWithRevisionCheck(const ClangBackEnd::FileContainer &fileContainer); + void updateTranslationUnitWithRevisionCheck(Core::IDocument *document); void updateChangeContentStartPosition(const QString &filePath, int position); void registerFallbackProjectPart(); + void updateTranslationUnitVisiblity(); + + bool isNotWaitingForCompletion() const; public: // for tests IpcSenderInterface *setIpcSender(IpcSenderInterface *ipcSender); @@ -159,13 +169,19 @@ private: void initializeBackend(); void initializeBackendWithCurrentData(); void registerCurrentProjectParts(); - void registerCurrentCppEditorDocuments(); + void restoreCppEditorDocuments(); + void resetCppEditorDocumentProcessors(); + void registerVisibleCppEditorDocumentAndMarkInvisibleDirty(); void registerCurrentCodeModelUiHeaders(); + void onBackendRestarted(); void onEditorAboutToClose(Core::IEditor *editor); void onCoreAboutToClose(); + void updateTranslationUnitVisiblity(const Utf8String ¤tEditorFilePath, + const Utf8StringVector &visibleEditorsFilePaths); + private: IpcReceiver m_ipcReceiver; ClangBackEnd::ConnectionClient m_connection; diff --git a/src/plugins/clangcodemodel/clangcodemodel.pro b/src/plugins/clangcodemodel/clangcodemodel.pro index e8578cbb7c..436e15b607 100644 --- a/src/plugins/clangcodemodel/clangcodemodel.pro +++ b/src/plugins/clangcodemodel/clangcodemodel.pro @@ -1,19 +1,13 @@ 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 +# 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 \ + clangactivationsequencecontextprocessor.cpp \ + clangactivationsequenceprocessor.cpp \ clangassistproposal.cpp \ clangassistproposalitem.cpp \ clangassistproposalmodel.cpp \ @@ -22,6 +16,7 @@ SOURCES += \ clangcompletionassistinterface.cpp \ clangcompletionassistprocessor.cpp \ clangcompletionassistprovider.cpp \ + clangcompletionchunkstotextconverter.cpp \ clangcompletioncontextanalyzer.cpp \ clangdiagnosticfilter.cpp \ clangdiagnosticmanager.cpp \ @@ -30,32 +25,16 @@ SOURCES += \ clangfixitoperation.cpp \ clangfixitoperationsextractor.cpp \ clangfunctionhintmodel.cpp \ + clanghighlightingmarksreporter.cpp \ clangmodelmanagersupport.cpp \ clangprojectsettings.cpp \ clangprojectsettingspropertiespage.cpp \ clangtextmark.cpp \ - clangutils.cpp \ - completionchunkstotextconverter.cpp \ - cppcreatemarkers.cpp \ - cxprettyprinter.cpp \ - diagnostic.cpp \ - fastindexer.cpp \ - pchinfo.cpp \ - pchmanager.cpp \ - raii/scopedclangoptions.cpp \ - semanticmarker.cpp \ - sourcelocation.cpp \ - sourcemarker.cpp \ - symbol.cpp \ - unit.cpp \ - unsavedfiledata.cpp \ - utils.cpp \ - utils_p.cpp - + clangutils.cpp HEADERS += \ - activationsequencecontextprocessor.h \ - activationsequenceprocessor.h \ + clangactivationsequencecontextprocessor.h \ + clangactivationsequenceprocessor.h \ clangassistproposal.h \ clangassistproposalitem.h \ clangassistproposalmodel.h \ @@ -64,7 +43,9 @@ HEADERS += \ clangcompletionassistinterface.h \ clangcompletionassistprocessor.h \ clangcompletionassistprovider.h \ + clangcompletionchunkstotextconverter.h \ clangcompletioncontextanalyzer.h \ + clangconstants.h \ clangdiagnosticfilter.h \ clangdiagnosticmanager.h \ clangeditordocumentparser.h \ @@ -72,45 +53,12 @@ HEADERS += \ clangfixitoperation.h \ clangfixitoperationsextractor.h \ clangfunctionhintmodel.h \ - clang_global.h \ + clanghighlightingmarksreporter.h \ clangmodelmanagersupport.h \ clangprojectsettings.h \ clangprojectsettingspropertiespage.h \ clangtextmark.h \ clangutils.h \ - completionchunkstotextconverter.h \ - constants.h \ - cppcreatemarkers.h \ - cxprettyprinter.h \ - cxraii.h \ - diagnostic.h \ - fastindexer.h \ - pchinfo.h \ - pchmanager.h \ - raii/scopedclangoptions.h \ - semanticmarker.h \ - sourcelocation.h \ - sourcemarker.h \ - symbol.h \ - unit.h \ - unsavedfiledata.h \ - utils.h \ - utils_p.h - - -contains(DEFINES, CLANG_INDEXING) { - HEADERS += \ - clangindexer.h \ - index.h \ - indexer.h -# dependencygraph.h \ - - SOURCES += \ - clangindexer.cpp \ - index.cpp \ - indexer.cpp -# dependencygraph.cpp \ -} FORMS += clangprojectsettingspropertiespage.ui diff --git a/src/plugins/clangcodemodel/clangcodemodel.qbs b/src/plugins/clangcodemodel/clangcodemodel.qbs index 858903aa77..eccd34b53b 100644 --- a/src/plugins/clangcodemodel/clangcodemodel.qbs +++ b/src/plugins/clangcodemodel/clangcodemodel.qbs @@ -20,124 +20,65 @@ QtcPlugin { "QmakeProjectManager", ] - property bool clangCompletion: true - property bool clangHighlighting: true - property bool clangIndexing: false - 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. defines.push('CLANG_VERSION="' + llvmVersion + '"'); defines.push('CLANG_RESOURCE_DIR="' + llvmLibDir + '/clang/' + llvmVersion + '/include"'); - if (clangCompletion) - defines.push("CLANG_COMPLETION"); - if (clangHighlighting) - defines.push("CLANG_HIGHLIGHTING"); - if (clangIndexing) - defines.push("CLANG_INDEXING"); return defines; } - Group { - name: "Completion support" - condition: product.clangCompletion - files: [ - "activationsequencecontextprocessor.cpp", - "activationsequencecontextprocessor.h", - "activationsequenceprocessor.cpp", - "activationsequenceprocessor.h", - "clangassistproposal.cpp", - "clangassistproposal.h", - "clangassistproposalitem.cpp", - "clangassistproposalitem.h", - "clangassistproposalmodel.cpp", - "clangassistproposalmodel.h", - "clangcompletionassistinterface.cpp", - "clangcompletionassistinterface.h", - "clangcompletionassistprocessor.cpp", - "clangcompletionassistprocessor.h", - "clangcompletionassistprovider.cpp", - "clangcompletionassistprovider.h", - "clangfunctionhintmodel.cpp", - "clangfunctionhintmodel.h", - ] - } - - Group { - name: "Highlighting support" - condition: product.clangHighlighting - files: [ - "cppcreatemarkers.cpp", - "cppcreatemarkers.h", - ] - } - - Group { - name: "Indexing support" - condition: product.clangIndexing - files: [ - "clangindexer.cpp", - "clangindexer.h", - "index.cpp", - "index.h", - "indexer.cpp", - "indexer.h", - // "dependencygraph.h", - // "dependencygraph.cpp" - ] - } - - Group { - name: "Tests" - condition: project.testsEnabled - prefix: "test/" - files: [ - "data/clangtestdata.qrc", - "clangcodecompletion_test.cpp", - "clangcodecompletion_test.h", - ] - } - - Group { - name: "Test resources" - prefix: "test/data/" - fileTags: "none" - files: [ "*" ] - excludeFiles: "clangtestdata.qrc" - } - files: [ - "clang_global.h", + "clangactivationsequencecontextprocessor.cpp", + "clangactivationsequencecontextprocessor.h", + "clangactivationsequenceprocessor.cpp", + "clangactivationsequenceprocessor.h", + "clangassistproposal.cpp", + "clangassistproposal.h", + "clangassistproposalitem.cpp", + "clangassistproposalitem.h", + "clangassistproposalmodel.cpp", + "clangassistproposalmodel.h", + "clangbackendipcintegration.cpp", + "clangbackendipcintegration.h", + "clangcodemodelplugin.cpp", + "clangcodemodelplugin.h", + "clangcompletionassistinterface.cpp", + "clangcompletionassistinterface.h", + "clangcompletionassistprocessor.cpp", + "clangcompletionassistprocessor.h", + "clangcompletionassistprovider.cpp", + "clangcompletionassistprovider.h", + "clangcompletionchunkstotextconverter.cpp", + "clangcompletionchunkstotextconverter.h", "clangcompletioncontextanalyzer.cpp", "clangcompletioncontextanalyzer.h", - "clangeditordocumentparser.cpp", - "clangeditordocumentparser.h", - "clangeditordocumentprocessor.cpp", - "clangeditordocumentprocessor.h", + "clangconstants.h", "clangdiagnosticfilter.cpp", "clangdiagnosticfilter.h", "clangdiagnosticmanager.cpp", "clangdiagnosticmanager.h", + "clangeditordocumentparser.cpp", + "clangeditordocumentparser.h", + "clangeditordocumentprocessor.cpp", + "clangeditordocumentprocessor.h", "clangfixitoperation.cpp", "clangfixitoperation.h", "clangfixitoperationsextractor.cpp", "clangfixitoperationsextractor.h", + "clangfunctionhintmodel.cpp", + "clangfunctionhintmodel.h", + "clanghighlightingmarksreporter.cpp", + "clanghighlightingmarksreporter.h", "clangmodelmanagersupport.cpp", "clangmodelmanagersupport.h", - "clangcodemodelplugin.cpp", - "clangcodemodelplugin.h", "clangprojectsettings.cpp", "clangprojectsettings.h", "clangprojectsettingspropertiespage.cpp", @@ -147,39 +88,24 @@ QtcPlugin { "clangtextmark.h", "clangutils.cpp", "clangutils.h", - "clangbackendipcintegration.cpp", - "clangbackendipcintegration.h", - "completionchunkstotextconverter.cpp", - "completionchunkstotextconverter.h", - "constants.h", - "cxprettyprinter.cpp", - "cxprettyprinter.h", - "cxraii.h", - "diagnostic.cpp", - "diagnostic.h", - "fastindexer.cpp", - "fastindexer.h", - "pchinfo.cpp", - "pchinfo.h", - "pchmanager.cpp", - "pchmanager.h", - "semanticmarker.cpp", - "semanticmarker.h", - "sourcelocation.cpp", - "sourcelocation.h", - "sourcemarker.cpp", - "sourcemarker.h", - "symbol.cpp", - "symbol.h", - "unit.cpp", - "unit.h", - "unsavedfiledata.cpp", - "unsavedfiledata.h", - "utils.cpp", - "utils.h", - "utils_p.cpp", - "utils_p.h", - "raii/scopedclangoptions.cpp", - "raii/scopedclangoptions.h", ] + + Group { + name: "Tests" + condition: project.testsEnabled + prefix: "test/" + files: [ + "data/clangtestdata.qrc", + "clangcodecompletion_test.cpp", + "clangcodecompletion_test.h", + ] + } + + Group { + name: "Test resources" + prefix: "test/data/" + fileTags: "none" + files: [ "*" ] + excludeFiles: "clangtestdata.qrc" + } } diff --git a/src/plugins/clangcodemodel/clangcodemodelplugin.cpp b/src/plugins/clangcodemodel/clangcodemodelplugin.cpp index 80b098c940..ea7aa9c3d1 100644 --- a/src/plugins/clangcodemodel/clangcodemodelplugin.cpp +++ b/src/plugins/clangcodemodel/clangcodemodelplugin.cpp @@ -30,10 +30,8 @@ #include "clangcodemodelplugin.h" +#include "clangconstants.h" #include "clangprojectsettingspropertiespage.h" -#include "constants.h" -#include "pchmanager.h" -#include "utils.h" #ifdef WITH_TESTS # include "test/clangcodecompletion_test.h" @@ -50,7 +48,9 @@ namespace ClangCodeModel { namespace Internal { -static void initializeTextMarks() +namespace { + +void initializeTextMarks() { TextEditor::TextMark::setCategoryColor(Core::Id(Constants::CLANG_WARNING), Utils::Theme::ClangCodeModel_Warning_TextMarkColor); @@ -58,10 +58,7 @@ static void initializeTextMarks() Utils::Theme::ClangCodeModel_Error_TextMarkColor); } -ClangCodeModelPlugin::ClangCodeModelPlugin() -{ - qRegisterMetaType<CppTools::ProjectPart::Ptr>(); -} +} // anonymous namespace bool ClangCodeModelPlugin::initialize(const QStringList &arguments, QString *errorMessage) { @@ -75,25 +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 Indexer - auto cppModelManager = CppTools::CppModelManager::instance(); -#ifdef CLANG_INDEXING - m_indexer.reset(new ClangIndexer); - cppModelManager->setIndexingSupport(m_indexer->indexingSupport()); -#endif // CLANG_INDEXING - - // Set up PchManager - PchManager *pchManager = new PchManager(this); - ProjectExplorer::SessionManager *sessionManager = ProjectExplorer::SessionManager::instance(); - connect(sessionManager, &ProjectExplorer::SessionManager::aboutToRemoveProject, - pchManager, &PchManager::onAboutToRemoveProject); - connect(cppModelManager, &CppTools::CppModelManager::projectPartsUpdated, - pchManager, &PchManager::onProjectPartsUpdated); - // Register ModelManagerSupportProvider + auto cppModelManager = CppTools::CppModelManager::instance(); cppModelManager->setClangModelManagerSupportProvider(&m_modelManagerSupportProvider); initializeTextMarks(); diff --git a/src/plugins/clangcodemodel/clangcodemodelplugin.h b/src/plugins/clangcodemodel/clangcodemodelplugin.h index 39d4ba6633..bba0f439c4 100644 --- a/src/plugins/clangcodemodel/clangcodemodelplugin.h +++ b/src/plugins/clangcodemodel/clangcodemodelplugin.h @@ -33,14 +33,8 @@ #include "clangmodelmanagersupport.h" -#ifdef CLANG_INDEXING -# include "clangindexer.h" -#endif // CLANG_INDEXING - #include <extensionsystem/iplugin.h> -#include <QScopedPointer> - namespace ClangCodeModel { namespace Internal { @@ -50,16 +44,11 @@ class ClangCodeModelPlugin: public ExtensionSystem::IPlugin Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ClangCodeModel.json") public: - ClangCodeModelPlugin(); - bool initialize(const QStringList &arguments, QString *errorMessage); void extensionsInitialized(); private: ModelManagerSupportProviderClang m_modelManagerSupportProvider; -#ifdef CLANG_INDEXING - QScopedPointer<ClangIndexer> m_indexer; -#endif // CLANG_INDEXING #ifdef WITH_TESTS QList<QObject *> createTestObjects() const; diff --git a/src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri b/src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri index 35ba6f84c0..0515875a4a 100644 --- a/src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri +++ b/src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri @@ -1,15 +1,19 @@ INCLUDEPATH += $$PWD -SOURCES += $$PWD/completionchunkstotextconverter.cpp \ - $$PWD/activationsequenceprocessor.cpp \ - $$PWD/activationsequencecontextprocessor.cpp \ - $$PWD/clangcompletioncontextanalyzer.cpp \ - $$PWD/clangdiagnosticfilter.cpp \ - $$PWD/clangfixitoperation.cpp +SOURCES += \ + $$PWD/clangactivationsequencecontextprocessor.cpp \ + $$PWD/clangactivationsequenceprocessor.cpp \ + $$PWD/clangcompletionchunkstotextconverter.cpp \ + $$PWD/clangcompletioncontextanalyzer.cpp \ + $$PWD/clangdiagnosticfilter.cpp \ + $$PWD/clangfixitoperation.cpp \ + $$PWD/clanghighlightingmarksreporter.cpp -HEADERS += $$PWD/completionchunkstotextconverter.h \ - $$PWD/activationsequenceprocessor.h \ - $$PWD/activationsequencecontextprocessor.h \ - $$PWD/clangcompletioncontextanalyzer.h \ - $$PWD/clangdiagnosticfilter.h \ - $$PWD/clangfixitoperation.h +HEADERS += \ + $$PWD/clangactivationsequencecontextprocessor.h \ + $$PWD/clangactivationsequenceprocessor.h \ + $$PWD/clangcompletionchunkstotextconverter.h \ + $$PWD/clangcompletioncontextanalyzer.h \ + $$PWD/clangdiagnosticfilter.h \ + $$PWD/clangfixitoperation.h \ + $$PWD/clanghighlightingmarksreporter.h diff --git a/src/plugins/clangcodemodel/clangcompletionassistinterface.cpp b/src/plugins/clangcodemodel/clangcompletionassistinterface.cpp index ec46846ccb..b8fbb2f4bc 100644 --- a/src/plugins/clangcodemodel/clangcompletionassistinterface.cpp +++ b/src/plugins/clangcodemodel/clangcompletionassistinterface.cpp @@ -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 UnsavedFiles &ClangCompletionAssistInterface::unsavedFiles() const -{ - return m_unsavedFiles; -} - } // namespace Internal } // namespace ClangCodeModel diff --git a/src/plugins/clangcodemodel/clangcompletionassistinterface.h b/src/plugins/clangcodemodel/clangcompletionassistinterface.h index 21a9e8d4ab..11bd0d7ddd 100644 --- a/src/plugins/clangcodemodel/clangcompletionassistinterface.h +++ b/src/plugins/clangcodemodel/clangcompletionassistinterface.h @@ -32,8 +32,7 @@ #define CLANGCODEMODEL_INTERNAL_CLANGCOMPLETIONASSISTINTERFACE_H #include "clangbackendipcintegration.h" -#include "pchinfo.h" -#include "utils.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 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; - 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; }; diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp index 70dab8f558..fe437f52fc 100644 --- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp +++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp @@ -30,7 +30,7 @@ #include "clangassistproposalitem.h" -#include "activationsequenceprocessor.h" +#include "clangactivationsequenceprocessor.h" #include "clangassistproposal.h" #include "clangassistproposalmodel.h" #include "clangcompletionassistprocessor.h" @@ -38,7 +38,7 @@ #include "clangeditordocumentprocessor.h" #include "clangfunctionhintmodel.h" #include "clangutils.h" -#include "completionchunkstotextconverter.h" +#include "clangcompletionchunkstotextconverter.h" #include <utils/qtcassert.h> @@ -342,13 +342,16 @@ IAssistProposal *ClangCompletionAssistProcessor::startCompletionHelper() case ClangCompletionContextAnalyzer::PassThroughToLibClang: { m_addSnippets = m_completionOperator == T_EOF_SYMBOL; m_sentRequestType = NormalCompletion; - sendCompletionRequest(analyzer.positionForClang(), modifiedFileContent); + const bool requestSent = sendCompletionRequest(analyzer.positionForClang(), + modifiedFileContent); + setPerformWasApplicable(requestSent); break; } case ClangCompletionContextAnalyzer::PassThroughToLibClangAfterLeftParen: { m_sentRequestType = FunctionHintCompletion; m_functionName = analyzer.functionName(); - sendCompletionRequest(analyzer.positionForClang(), QByteArray()); + const bool requestSent = sendCompletionRequest(analyzer.positionForClang(), QByteArray()); + setPerformWasApplicable(requestSent); break; } default: @@ -702,15 +705,34 @@ bool shouldSendDocumentForCompletion(const QString &filePath, return true; } -void setLastCompletionPositionAndDocumentRevision(const QString &filePath, - int completionPosition) +bool shouldSendCodeCompletion(const QString &filePath, + int completionPosition) { auto *document = cppDocument(filePath); if (document) { - document->sendTracker().setLastCompletionPosition(completionPosition); - document->sendTracker().setLastSentRevision(document->revision()); + auto &sendTracker = document->sendTracker(); + return sendTracker.shouldSendCompletion(completionPosition); } + + return true; +} + +void setLastDocumentRevision(const QString &filePath) +{ + auto *document = cppDocument(filePath); + + if (document) + document->sendTracker().setLastSentRevision(int(document->revision())); +} + +void setLastCompletionPosition(const QString &filePath, + int completionPosition) +{ + auto *document = cppDocument(filePath); + + if (document) + document->sendTracker().setLastCompletionPosition(completionPosition); } QString projectPartIdForEditorDocument(const QString &filePath) @@ -726,7 +748,7 @@ QString projectPartIdForEditorDocument(const QString &filePath) } } -void ClangCompletionAssistProcessor::sendCompletionRequest(int position, +bool ClangCompletionAssistProcessor::sendCompletionRequest(int position, const QByteArray &customFileContent) { int line, column; @@ -735,17 +757,22 @@ void ClangCompletionAssistProcessor::sendCompletionRequest(int position, const QString filePath = m_interface->fileName(); - if (shouldSendDocumentForCompletion(filePath, position)) { - sendFileContent(customFileContent); - setLastCompletionPositionAndDocumentRevision(filePath, position); + auto &ipcCommunicator = m_interface->ipcCommunicator(); + + if (shouldSendCodeCompletion(filePath, position) + || ipcCommunicator.isNotWaitingForCompletion()) { + if (shouldSendDocumentForCompletion(filePath, position)) { + sendFileContent(customFileContent); + setLastDocumentRevision(filePath); + } + + const QString projectPartId = projectPartIdForEditorDocument(filePath); + ipcCommunicator.completeCode(this, filePath, uint(line), uint(column), projectPartId); + setLastCompletionPosition(filePath, position); + return true; } - const QString projectPartId = projectPartIdForEditorDocument(filePath); - m_interface->ipcCommunicator().completeCode(this, - filePath, - uint(line), - uint(column), - projectPartId); + return false; } TextEditor::IAssistProposal *ClangCompletionAssistProcessor::createProposal() const diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.h b/src/plugins/clangcodemodel/clangcompletionassistprocessor.h index 4cecf8a31e..6a8abddcb7 100644 --- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.h +++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.h @@ -84,7 +84,7 @@ private: UnsavedFileContentInfo unsavedFileContent(const QByteArray &customFileContent) const; void sendFileContent(const QByteArray &customFileContent); - void sendCompletionRequest(int position, const QByteArray &customFileContent); + bool sendCompletionRequest(int position, const QByteArray &customFileContent); void handleAvailableCompletions(const CodeCompletions &completions); bool handleAvailableFunctionHintCompletions(const CodeCompletions &completions); diff --git a/src/plugins/clangcodemodel/clangcompletionassistprovider.cpp b/src/plugins/clangcodemodel/clangcompletionassistprovider.cpp index 4aa358ab08..d9e6b57771 100644 --- a/src/plugins/clangcodemodel/clangcompletionassistprovider.cpp +++ b/src/plugins/clangcodemodel/clangcompletionassistprovider.cpp @@ -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); } diff --git a/src/plugins/clangcodemodel/completionchunkstotextconverter.cpp b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp index 68e245f636..43e6c86f76 100644 --- a/src/plugins/clangcodemodel/completionchunkstotextconverter.cpp +++ b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.cpp @@ -28,7 +28,7 @@ ** ****************************************************************************/ -#include "completionchunkstotextconverter.h" +#include "clangcompletionchunkstotextconverter.h" #include <algorithm> #include <functional> diff --git a/src/plugins/clangcodemodel/completionchunkstotextconverter.h b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h index f80ab1a383..f80ab1a383 100644 --- a/src/plugins/clangcodemodel/completionchunkstotextconverter.h +++ b/src/plugins/clangcodemodel/clangcompletionchunkstotextconverter.h diff --git a/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp b/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp index eaa2b3d90a..f59b21db33 100644 --- a/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp +++ b/src/plugins/clangcodemodel/clangcompletioncontextanalyzer.cpp @@ -31,8 +31,8 @@ #include "clangcompletioncontextanalyzer.h" -#include "activationsequenceprocessor.h" -#include "activationsequencecontextprocessor.h" +#include "clangactivationsequencecontextprocessor.h" +#include "clangactivationsequenceprocessor.h" #include <texteditor/codeassist/assistinterface.h> diff --git a/src/plugins/clangcodemodel/fastindexer.h b/src/plugins/clangcodemodel/clangconstants.h index 1c63a4435f..e02e9c72d3 100644 --- a/src/plugins/clangcodemodel/fastindexer.h +++ b/src/plugins/clangcodemodel/clangconstants.h @@ -28,23 +28,17 @@ ** ****************************************************************************/ -#ifndef FASTINDEXER_H -#define FASTINDEXER_H - -#include "unit.h" +#ifndef CLANGCONSTANTS_H +#define CLANGCONSTANTS_H namespace ClangCodeModel { -namespace Internal { - -class FastIndexer -{ -public: - virtual ~FastIndexer() = 0; +namespace Constants { - virtual void indexNow(Unit::Ptr unit) = 0; -}; +const char CLANG_MODELMANAGERSUPPORT_ID[] = "ClangCodeModel.ClangCodeModel"; +const char CLANG_ERROR[] = "Clang.Error"; +const char CLANG_WARNING[] = "Clang.Warning"; -} // Internal namespace -} // ClangCodeModel namespace +} // namespace Constants +} // namespace ClangCodeModel -#endif // FASTINDEXER_H +#endif // CLANGCONSTANTS_H diff --git a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp index 13544424bd..1e94d55aef 100644 --- a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp +++ b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp @@ -31,7 +31,9 @@ #include "clangdiagnosticfilter.h" #include "clangdiagnosticmanager.h" +#include <texteditor/fontsettings.h> #include <texteditor/textdocument.h> +#include <texteditor/texteditorsettings.h> #include <utils/fileutils.h> #include <utils/qtcassert.h> @@ -53,7 +55,7 @@ QTextEdit::ExtraSelection createExtraSelections(const QTextCharFormat &mainforma void addRangeSelections(const ClangBackEnd::DiagnosticContainer &diagnostic, QTextDocument *textDocument, - const QTextCharFormat &rangeFormat, + const QTextCharFormat &contextFormat, const QString &diagnosticText, QList<QTextEdit::ExtraSelection> &extraSelections) { @@ -62,7 +64,7 @@ void addRangeSelections(const ClangBackEnd::DiagnosticContainer &diagnostic, cursor.setPosition(int(range.start().offset())); cursor.setPosition(int(range.end().offset()), QTextCursor::KeepAnchor); - auto extraSelection = createExtraSelections(rangeFormat, cursor, diagnosticText); + auto extraSelection = createExtraSelections(contextFormat, cursor, diagnosticText); extraSelections.push_back(std::move(extraSelection)); } @@ -116,7 +118,7 @@ QString diagnosticText(const ClangBackEnd::DiagnosticContainer &diagnostic) void addSelections(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics, QTextDocument *textDocument, const QTextCharFormat &mainFormat, - const QTextCharFormat &rangeFormat, + const QTextCharFormat &contextFormat, QList<QTextEdit::ExtraSelection> &extraSelections) { for (auto &&diagnostic : diagnostics) { @@ -125,7 +127,7 @@ void addSelections(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics auto text = diagnosticText(diagnostic); auto extraSelection = createExtraSelections(mainFormat, cursor, text); - addRangeSelections(diagnostic, textDocument, rangeFormat, text, extraSelections); + addRangeSelections(diagnostic, textDocument, contextFormat, text, extraSelections); extraSelections.push_back(std::move(extraSelection)); } @@ -135,30 +137,25 @@ void addWarningSelections(const QVector<ClangBackEnd::DiagnosticContainer> &diag QTextDocument *textDocument, QList<QTextEdit::ExtraSelection> &extraSelections) { - QTextCharFormat warningFormat; - warningFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline); - warningFormat.setUnderlineColor(QColor(180, 180, 0, 255)); + const auto fontSettings = TextEditor::TextEditorSettings::instance()->fontSettings(); - QTextCharFormat warningRangeFormat; - warningRangeFormat.setUnderlineStyle(QTextCharFormat::DotLine); - warningRangeFormat.setUnderlineColor(QColor(180, 180, 0, 255)); + QTextCharFormat warningFormat = fontSettings.toTextCharFormat(TextEditor::C_WARNING); - addSelections(diagnostics, textDocument, warningFormat, warningRangeFormat, extraSelections); + QTextCharFormat warningContextFormat = fontSettings.toTextCharFormat(TextEditor::C_WARNING_CONTEXT); + + addSelections(diagnostics, textDocument, warningFormat, warningContextFormat, extraSelections); } void addErrorSelections(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics, QTextDocument *textDocument, QList<QTextEdit::ExtraSelection> &extraSelections) { - QTextCharFormat errorFormat; - errorFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline); - errorFormat.setUnderlineColor(QColor(255, 0, 0, 255)); + const auto fontSettings = TextEditor::TextEditorSettings::instance()->fontSettings(); - QTextCharFormat errorRangeFormat; - errorRangeFormat.setUnderlineStyle(QTextCharFormat::DotLine); - errorRangeFormat.setUnderlineColor(QColor(255, 0, 0, 255)); + QTextCharFormat errorFormat = fontSettings.toTextCharFormat(TextEditor::C_ERROR); + QTextCharFormat errorContextFormat = fontSettings.toTextCharFormat(TextEditor::C_ERROR_CONTEXT); - addSelections(diagnostics, textDocument, errorFormat, errorRangeFormat, extraSelections); + addSelections(diagnostics, textDocument, errorFormat, errorContextFormat, extraSelections); } } // anonymous diff --git a/src/plugins/clangcodemodel/clangeditordocumentparser.cpp b/src/plugins/clangcodemodel/clangeditordocumentparser.cpp index caeefd2267..4b2daaa737 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentparser.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentparser.cpp @@ -29,111 +29,22 @@ ****************************************************************************/ #include "clangeditordocumentparser.h" -#include "clangutils.h" -#include "pchinfo.h" -#include "pchmanager.h" - -#include <cpptools/cppmodelmanager.h> -#include <cpptools/cppprojects.h> -#include <cpptools/cppworkingcopy.h> - -#include <utils/hostosinfo.h> -#include <utils/qtcassert.h> - -#include <QLoggingCategory> - -static Q_LOGGING_CATEGORY(log, "qtc.clangcodemodel.clangeditordocumentparser") - -namespace { - -QStringList createOptions(const QString &filePath, - const CppTools::ProjectPart::Ptr &part, - bool includeSpellCheck = false) -{ - using namespace ClangCodeModel; - - QStringList options; - if (part.isNull()) - return options; - - if (includeSpellCheck) - options += QLatin1String("-fspell-checking"); - - options += ClangCodeModel::Utils::createClangOptions(part, filePath); - - if (Internal::PchInfo::Ptr pchInfo = Internal::PchManager::instance()->pchInfo(part)) - options.append(ClangCodeModel::Utils::createPCHInclusionOptions(pchInfo->fileName())); - - return options; -} - -QString messageLine(const QStringList &options, const QString &fileName) -{ - const QStringList allOptions = QStringList(options) - << QLatin1String("-fsyntax-only") << fileName; - QStringList allOptionsQuoted; - foreach (const QString &option, allOptions) - allOptionsQuoted.append(QLatin1Char('\'') + option + QLatin1Char('\'')); - return ::Utils::HostOsInfo::withExecutableSuffix(QLatin1String("clang")) - + QLatin1Char(' ') + allOptionsQuoted.join(QLatin1Char(' ')); -} - -} // anonymous namespace namespace ClangCodeModel { ClangEditorDocumentParser::ClangEditorDocumentParser(const QString &filePath) : BaseEditorDocumentParser(filePath) - , m_marker(new ClangCodeModel::SemanticMarker) { BaseEditorDocumentParser::Configuration config = configuration(); config.stickToPreviousProjectPart = false; setConfiguration(config); } -void ClangEditorDocumentParser::updateHelper(const BaseEditorDocumentParser::InMemoryInfo &info) +void ClangEditorDocumentParser::updateHelper(const BaseEditorDocumentParser::InMemoryInfo &) { - QTC_ASSERT(m_marker, return); - - // Determine project part State state_ = state(); state_.projectPart = determineProjectPart(filePath(), configuration(), state_); setState(state_); - emit projectPartDetermined(state_.projectPart); - - // Determine message line arguments - const QStringList options = createOptions(filePath(), state_.projectPart, true); - qCDebug(log, "Reparse options (cmd line equivalent): %s", - messageLine(options, filePath()).toUtf8().constData()); - - // Run - QTime t; t.start(); - QMutexLocker lock(m_marker->mutex()); - m_marker->setFileName(filePath()); - m_marker->setCompilationOptions(options); - const Internal::UnsavedFiles unsavedFiles = Utils::createUnsavedFiles(info.workingCopy, - info.modifiedFiles); - m_marker->reparse(unsavedFiles); - qCDebug(log) << "Reparse took" << t.elapsed() << "ms."; -} - -QList<Diagnostic> ClangEditorDocumentParser::diagnostics() const -{ - QTC_ASSERT(m_marker, return QList<Diagnostic>()); - QMutexLocker(m_marker->mutex()); - return m_marker->diagnostics(); -} - -QList<SemanticMarker::Range> ClangEditorDocumentParser::ifdefedOutBlocks() const -{ - QTC_ASSERT(m_marker, return QList<SemanticMarker::Range>()); - QMutexLocker(m_marker->mutex()); - return m_marker->ifdefedOutBlocks(); -} - -SemanticMarker::Ptr ClangEditorDocumentParser::semanticMarker() const -{ - return m_marker; } } // namespace ClangCodeModel diff --git a/src/plugins/clangcodemodel/clangeditordocumentparser.h b/src/plugins/clangcodemodel/clangeditordocumentparser.h index ef207749c2..7dc54732f3 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentparser.h +++ b/src/plugins/clangcodemodel/clangeditordocumentparser.h @@ -31,12 +31,8 @@ #ifndef CLANGEDITORDOCUMENTPARSER_H #define CLANGEDITORDOCUMENTPARSER_H -#include "semanticmarker.h" - #include <cpptools/baseeditordocumentparser.h> -namespace CppTools { class WorkingCopy; } - namespace ClangCodeModel { class ClangEditorDocumentParser : public CppTools::BaseEditorDocumentParser @@ -46,17 +42,8 @@ class ClangEditorDocumentParser : public CppTools::BaseEditorDocumentParser public: ClangEditorDocumentParser(const QString &filePath); - QList<Diagnostic> diagnostics() const; - QList<SemanticMarker::Range> ifdefedOutBlocks() const; - SemanticMarker::Ptr semanticMarker() const; - -signals: - void projectPartDetermined(CppTools::ProjectPart::Ptr projectPart); - private: - void updateHelper(const BaseEditorDocumentParser::InMemoryInfo &info) override; - - SemanticMarker::Ptr m_marker; + void updateHelper(const BaseEditorDocumentParser::InMemoryInfo &) override; }; } // namespace ClangCodeModel diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp index 5739960751..6dc870b3de 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp @@ -32,11 +32,9 @@ #include "clangfixitoperation.h" #include "clangfixitoperationsextractor.h" +#include "clanghighlightingmarksreporter.h" #include "clangmodelmanagersupport.h" #include "clangutils.h" -#include "cppcreatemarkers.h" -#include "diagnostic.h" -#include "pchinfo.h" #include <diagnosticcontainer.h> #include <sourcelocationcontainer.h> @@ -59,22 +57,6 @@ #include <QTextBlock> -namespace { - -typedef CPlusPlus::Document::DiagnosticMessage CppToolsDiagnostic; - -QList<TextEditor::BlockRange> toTextEditorBlocks( - const QList<ClangCodeModel::SemanticMarker::Range> &ranges) -{ - QList<TextEditor::BlockRange> result; - result.reserve(ranges.size()); - foreach (const ClangCodeModel::SemanticMarker::Range &range, ranges) - result.append(TextEditor::BlockRange(range.first, range.last)); - return result; -} - -} // anonymous namespace - namespace ClangCodeModel { namespace Internal { @@ -89,26 +71,12 @@ ClangEditorDocumentProcessor::ClangEditorDocumentProcessor( , m_semanticHighlighter(document) , m_builtinProcessor(document, /*enableSemanticHighlighter=*/ false) { - connect(m_parser.data(), &ClangEditorDocumentParser::projectPartDetermined, - this, &ClangEditorDocumentProcessor::onParserDeterminedProjectPart); - // Forwarding the semantic info from the builtin processor enables us to provide all // editor (widget) related features that are not yet implemented by the clang plugin. connect(&m_builtinProcessor, &CppTools::BuiltinEditorDocumentProcessor::cppDocumentUpdated, this, &ClangEditorDocumentProcessor::cppDocumentUpdated); connect(&m_builtinProcessor, &CppTools::BuiltinEditorDocumentProcessor::semanticInfoUpdated, this, &ClangEditorDocumentProcessor::semanticInfoUpdated); - - m_semanticHighlighter.setHighlightingRunner( - [this]() -> QFuture<TextEditor::HighlightingResult> { - const int firstLine = 1; - const int lastLine = baseTextDocument()->document()->blockCount(); - - CreateMarkers *createMarkers = CreateMarkers::create(m_parser->semanticMarker(), - baseTextDocument()->filePath().toString(), - firstLine, lastLine); - return createMarkers->start(); - }); } ClangEditorDocumentProcessor::~ClangEditorDocumentProcessor() @@ -125,7 +93,7 @@ ClangEditorDocumentProcessor::~ClangEditorDocumentProcessor() void ClangEditorDocumentProcessor::run() { - requestDiagnostics(); + updateTranslationUnitIfProjectPartExists(); // Run clang parser disconnect(&m_parserWatcher, &QFutureWatcher<void>::finished, @@ -153,7 +121,9 @@ void ClangEditorDocumentProcessor::recalculateSemanticInfoDetached(bool force) void ClangEditorDocumentProcessor::semanticRehighlight() { m_semanticHighlighter.updateFormatMapFromFontSettings(); - m_semanticHighlighter.run(); + + if (m_projectPart) + requestDocumentAnnotations(m_projectPart->id()); } CppTools::SemanticInfo ClangEditorDocumentProcessor::recalculateSemanticInfo() @@ -201,6 +171,36 @@ void ClangEditorDocumentProcessor::updateCodeWarnings(const QVector<ClangBackEnd } } +static QList<TextEditor::BlockRange> +toTextEditorBlocks(const QVector<ClangBackEnd::SourceRangeContainer> &ifdefedOutRanges) +{ + QList<TextEditor::BlockRange> blockRanges; + blockRanges.reserve(ifdefedOutRanges.size()); + + for (const auto &range : ifdefedOutRanges) + blockRanges.append(TextEditor::BlockRange(range.start().offset(),range.end().offset())); + + return blockRanges; +} + +void ClangEditorDocumentProcessor::updateHighlighting( + const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks, + const QVector<ClangBackEnd::SourceRangeContainer> &skippedPreprocessorRanges, + uint documentRevision) +{ + if (documentRevision == revision()) { + const auto skippedPreprocessorBlocks = toTextEditorBlocks(skippedPreprocessorRanges); + emit ifdefedOutBlocksUpdated(documentRevision, skippedPreprocessorBlocks); + + m_semanticHighlighter.setHighlightingRunner( + [highlightingMarks]() { + auto *reporter = new HighlightingMarksReporter(highlightingMarks); + return reporter->start(); + }); + m_semanticHighlighter.run(); + } +} + static int currentLine(const TextEditor::AssistInterface &assistInterface) { int line, column; @@ -219,9 +219,9 @@ TextEditor::QuickFixOperations ClangEditorDocumentProcessor::extraRefactoringOpe return extractor.extract(assistInterface.fileName(), currentLine(assistInterface)); } -ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainer() const +ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainerWithArguments() const { - return fileContainer(m_projectPart.data()); + return fileContainerWithArguments(m_projectPart.data()); } void ClangEditorDocumentProcessor::clearDiagnosticsWithFixIts() @@ -240,73 +240,56 @@ static bool isProjectPartLoadedOrIsFallback(CppTools::ProjectPart::Ptr projectPa && (projectPart->id().isEmpty() || ClangCodeModel::Utils::isProjectPartLoaded(projectPart)); } -void ClangEditorDocumentProcessor::updateProjectPartAndTranslationUnitForEditor( - CppTools::ProjectPart::Ptr projectPart) +void ClangEditorDocumentProcessor::updateProjectPartAndTranslationUnitForEditor() { - QTC_ASSERT(projectPart, return); + const CppTools::ProjectPart::Ptr projectPart = m_parser->projectPart(); if (isProjectPartLoadedOrIsFallback(projectPart)) { - updateTranslationUnitForEditor(projectPart.data()); - requestDiagnostics(projectPart.data()); + registerTranslationUnitForEditor(projectPart.data()); m_projectPart = projectPart; } } -void ClangEditorDocumentProcessor::onParserDeterminedProjectPart( - CppTools::ProjectPart::Ptr projectPart) -{ - updateProjectPartAndTranslationUnitForEditor(projectPart); -} - void ClangEditorDocumentProcessor::onParserFinished() { if (revision() != m_parserRevision) return; - // Emit ifdefed out blocks - const auto ifdefoutBlocks = toTextEditorBlocks(m_parser->ifdefedOutBlocks()); - emit ifdefedOutBlocksUpdated(revision(), ifdefoutBlocks); - - // Run semantic highlighter - m_semanticHighlighter.run(); + updateProjectPartAndTranslationUnitForEditor(); } -void ClangEditorDocumentProcessor::updateTranslationUnitForEditor(CppTools::ProjectPart *projectPart) +void ClangEditorDocumentProcessor::registerTranslationUnitForEditor(CppTools::ProjectPart *projectPart) { QTC_ASSERT(m_modelManagerSupport, return); IpcCommunicator &ipcCommunicator = m_modelManagerSupport->ipcCommunicator(); if (m_projectPart) { if (projectPart->id() != m_projectPart->id()) { - ipcCommunicator.unregisterTranslationUnitsForEditor({fileContainer()}); - ipcCommunicator.registerTranslationUnitsForEditor({fileContainer(projectPart)}); + ipcCommunicator.unregisterTranslationUnitsForEditor({fileContainerWithArguments()}); + ipcCommunicator.registerTranslationUnitsForEditor({fileContainerWithArguments(projectPart)}); } } else { - ipcCommunicator.registerTranslationUnitsForEditor({{fileContainer(projectPart)}}); + ipcCommunicator.registerTranslationUnitsForEditor({{fileContainerWithArguments(projectPart)}}); } } -void ClangEditorDocumentProcessor::requestDiagnostics(CppTools::ProjectPart *projectPart) +void ClangEditorDocumentProcessor::updateTranslationUnitIfProjectPartExists() { - if (!m_projectPart || projectPart->id() != m_projectPart->id()) { - IpcCommunicator &ipcCommunicator = m_modelManagerSupport->ipcCommunicator(); + if (m_projectPart) { + const ClangBackEnd::FileContainer fileContainer = fileContainerWithDocumentContent(m_projectPart->id()); - ipcCommunicator.requestDiagnostics({fileContainer(projectPart)}); + m_modelManagerSupport->ipcCommunicator().updateTranslationUnitWithRevisionCheck(fileContainer); } } -void ClangEditorDocumentProcessor::requestDiagnostics() +void ClangEditorDocumentProcessor::requestDocumentAnnotations(const QString &projectpartId) { - // Get diagnostics - if (m_projectPart) { - auto &ipcCommunicator = m_modelManagerSupport->ipcCommunicator(); - ipcCommunicator.requestDiagnostics({filePath(), - m_projectPart->id(), - baseTextDocument()->plainText(), - true, - revision()}); - } + const auto fileContainer = fileContainerWithDocumentContent(projectpartId); + + auto &ipcCommunicator = m_modelManagerSupport->ipcCommunicator(); + ipcCommunicator.requestDiagnostics(fileContainer); + ipcCommunicator.requestHighlighting(fileContainer); } static CppTools::ProjectPart projectPartForLanguageOption(CppTools::ProjectPart *projectPart) @@ -332,7 +315,7 @@ static QStringList fileArguments(const QString &filePath, CppTools::ProjectPart } ClangBackEnd::FileContainer -ClangEditorDocumentProcessor::fileContainer(CppTools::ProjectPart *projectPart) const +ClangEditorDocumentProcessor::fileContainerWithArguments(CppTools::ProjectPart *projectPart) const { const auto projectPartId = projectPart ? Utf8String::fromString(projectPart->id()) @@ -342,5 +325,15 @@ ClangEditorDocumentProcessor::fileContainer(CppTools::ProjectPart *projectPart) return {filePath(), projectPartId, Utf8StringVector(theFileArguments), revision()}; } +ClangBackEnd::FileContainer +ClangEditorDocumentProcessor::fileContainerWithDocumentContent(const QString &projectpartId) const +{ + return ClangBackEnd::FileContainer(filePath(), + projectpartId, + baseTextDocument()->plainText(), + true, + revision()); +} + } // namespace Internal } // namespace ClangCodeModel diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h index ded0258210..323f0f54a6 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.h +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.h @@ -43,6 +43,7 @@ namespace ClangBackEnd { class DiagnosticContainer; +class HighlightingMarkContainer; class FileContainer; } @@ -75,11 +76,14 @@ public: void updateCodeWarnings(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics, uint documentRevision); + void updateHighlighting(const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks, + const QVector<ClangBackEnd::SourceRangeContainer> &skippedPreprocessorRanges, + uint documentRevision); TextEditor::QuickFixOperations extraRefactoringOperations(const TextEditor::AssistInterface &assistInterface) override; - ClangBackEnd::FileContainer fileContainer() const; + ClangBackEnd::FileContainer fileContainerWithArguments() const; void clearDiagnosticsWithFixIts(); @@ -87,15 +91,15 @@ public: static ClangEditorDocumentProcessor *get(const QString &filePath); private slots: - void onParserDeterminedProjectPart(CppTools::ProjectPart::Ptr projectPart); void onParserFinished(); private: - void updateProjectPartAndTranslationUnitForEditor(CppTools::ProjectPart::Ptr projectPart); - void updateTranslationUnitForEditor(CppTools::ProjectPart *projectPart); - void requestDiagnostics(CppTools::ProjectPart *projectPart); - void requestDiagnostics(); - ClangBackEnd::FileContainer fileContainer(CppTools::ProjectPart *projectPart) const; + void updateProjectPartAndTranslationUnitForEditor(); + void registerTranslationUnitForEditor(CppTools::ProjectPart *projectPart); + void updateTranslationUnitIfProjectPartExists(); + void requestDocumentAnnotations(const QString &projectpartId); + ClangBackEnd::FileContainer fileContainerWithArguments(CppTools::ProjectPart *projectPart) const; + ClangBackEnd::FileContainer fileContainerWithDocumentContent(const QString &projectpartId) const; private: ClangDiagnosticManager m_diagnosticManager; diff --git a/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp b/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp index d037186b99..0ce334975f 100644 --- a/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp +++ b/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp @@ -30,7 +30,7 @@ #include "clangfunctionhintmodel.h" -#include "completionchunkstotextconverter.h" +#include "clangcompletionchunkstotextconverter.h" #include <cplusplus/SimpleLexer.h> diff --git a/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp b/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp new file mode 100644 index 0000000000..698f158c65 --- /dev/null +++ b/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** 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 "clanghighlightingmarksreporter.h" + +#include <cpptools/semantichighlighter.h> + +#include <QFuture> + +namespace { + +CppTools::SemanticHighlighter::Kind toCppToolsSemanticHighlighterKind( + ClangBackEnd::HighlightingType type) +{ + using ClangBackEnd::HighlightingType; + using CppTools::SemanticHighlighter; + + switch (type) { + case HighlightingType::Keyword: + return SemanticHighlighter::PseudoKeywordUse; + case HighlightingType::Function: + return SemanticHighlighter::FunctionUse; + case HighlightingType::VirtualFunction: + return SemanticHighlighter::VirtualMethodUse; + case HighlightingType::Type: + return SemanticHighlighter::TypeUse; + case HighlightingType::LocalVariable: + return SemanticHighlighter::LocalUse; + case HighlightingType::Field: + return SemanticHighlighter::FieldUse; + case HighlightingType::GlobalVariable: + return SemanticHighlighter::Unknown; + case HighlightingType::Enumeration: + return SemanticHighlighter::EnumerationUse; + case HighlightingType::Label: + return SemanticHighlighter::LabelUse; + case HighlightingType::Preprocessor: + return SemanticHighlighter::MacroUse; + default: + return SemanticHighlighter::Unknown; + } + + Q_UNREACHABLE(); +} + +TextEditor::HighlightingResult toHighlightingResult( + const ClangBackEnd::HighlightingMarkContainer &highlightingMark) +{ + const auto highlighterKind = toCppToolsSemanticHighlighterKind(highlightingMark.type()); + + return TextEditor::HighlightingResult(highlightingMark.line(), + highlightingMark.column(), + highlightingMark.length(), + highlighterKind); +} + +} // anonymous + +namespace ClangCodeModel { + +HighlightingMarksReporter::HighlightingMarksReporter( + const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks) + : m_highlightingMarks(highlightingMarks) +{ + m_chunksToReport.reserve(m_chunkSize + 1); +} + +void HighlightingMarksReporter::reportChunkWise( + const TextEditor::HighlightingResult &highlightingResult) +{ + if (m_chunksToReport.size() >= m_chunkSize) { + if (m_flushRequested && highlightingResult.line != m_flushLine) { + reportAndClearCurrentChunks(); + } else if (!m_flushRequested) { + m_flushRequested = true; + m_flushLine = highlightingResult.line; + } + } + + m_chunksToReport.append(highlightingResult); +} + +void HighlightingMarksReporter::reportAndClearCurrentChunks() +{ + m_flushRequested = false; + m_flushLine = 0; + + if (!m_chunksToReport.isEmpty()) { + reportResults(m_chunksToReport); + m_chunksToReport.erase(m_chunksToReport.begin(), m_chunksToReport.end()); + } +} + +void HighlightingMarksReporter::setChunkSize(int chunkSize) +{ + m_chunkSize = chunkSize; +} + +void HighlightingMarksReporter::run() +{ + run_internal(); + reportFinished(); +} + +void HighlightingMarksReporter::run_internal() +{ + if (isCanceled()) + return; + + for (const auto &highlightingMark : m_highlightingMarks) + reportChunkWise(toHighlightingResult(highlightingMark)); + + if (isCanceled()) + return; + + reportAndClearCurrentChunks(); +} + +QFuture<TextEditor::HighlightingResult> HighlightingMarksReporter::start() +{ + this->setRunnable(this); + this->reportStarted(); + QFuture<TextEditor::HighlightingResult> future = this->future(); + QThreadPool::globalInstance()->start(this, QThread::LowestPriority); + return future; +} + +} // namespace ClangCodeModel diff --git a/src/plugins/clangcodemodel/raii/scopedclangoptions.h b/src/plugins/clangcodemodel/clanghighlightingmarksreporter.h index 45ba6063ba..54ed8e3d2a 100644 --- a/src/plugins/clangcodemodel/raii/scopedclangoptions.h +++ b/src/plugins/clangcodemodel/clanghighlightingmarksreporter.h @@ -28,46 +28,51 @@ ** ****************************************************************************/ -#ifndef CLANGCODEMODEL_SCOPEDCLANGOPTIONS_H -#define CLANGCODEMODEL_SCOPEDCLANGOPTIONS_H +#ifndef CLANGCODEMODEL_HIGHLIGHTINGMARKSREPORTER_H +#define CLANGCODEMODEL_HIGHLIGHTINGMARKSREPORTER_H -#include "../clang_global.h" -#include <QStringList> -#include <QSharedPointer> +#include <QFutureInterface> +#include <QObject> +#include <QRunnable> +#include <QThreadPool> + +#include <texteditor/semantichighlighter.h> + +#include <clangbackendipc/highlightingmarkcontainer.h> namespace ClangCodeModel { -class CLANG_EXPORT ScopedClangOptions +class HighlightingMarksReporter: + public QObject, + public QRunnable, + public QFutureInterface<TextEditor::HighlightingResult> { + Q_OBJECT + public: - ScopedClangOptions(const QStringList &options); - ~ScopedClangOptions(); + HighlightingMarksReporter(const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks); - const char **data() const; - int size() const; + void setChunkSize(int chunkSize); -private: - void release(); + QFuture<TextEditor::HighlightingResult> start(); - int m_size; - const char **m_rawOptions; -}; +private: + void run() override; + void run_internal(); -class CLANG_EXPORT SharedClangOptions -{ -public: - SharedClangOptions(); - SharedClangOptions(const QStringList &options); + void reportChunkWise(const TextEditor::HighlightingResult &highlightingResult); + void reportAndClearCurrentChunks(); - void reloadOptions(const QStringList &options); +private: + QVector<ClangBackEnd::HighlightingMarkContainer> m_highlightingMarks; + QVector<TextEditor::HighlightingResult> m_chunksToReport; - const char **data() const; - int size() const; + int m_chunkSize = 100; -private: - QSharedPointer<ScopedClangOptions> d; + bool m_flushRequested = false; + unsigned m_flushLine = 0; }; } // namespace ClangCodeModel -#endif // CLANGCODEMODEL_SCOPEDCLANGOPTIONS_H +#endif // CLANGCODEMODEL_HIGHLIGHTINGMARKSREPORTER_H diff --git a/src/plugins/clangcodemodel/clangindexer.cpp b/src/plugins/clangcodemodel/clangindexer.cpp deleted file mode 100644 index c8d171ba56..0000000000 --- a/src/plugins/clangcodemodel/clangindexer.cpp +++ /dev/null @@ -1,172 +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 "clangindexer.h" -#include "clangutils.h" -#include "indexer.h" - -#include <coreplugin/icore.h> -#include <coreplugin/progressmanager/progressmanager.h> -#include <cpptools/cppmodelmanager.h> -#include <projectexplorer/session.h> - -#include <QDir> - -using namespace ClangCodeModel; -using namespace ClangCodeModel::Internal; - -ClangIndexingSupport::ClangIndexingSupport(ClangIndexer *indexer) - : m_indexer(indexer) -{ -} - -ClangIndexingSupport::~ClangIndexingSupport() -{ -} - -QFuture<void> ClangIndexingSupport::refreshSourceFiles( - const QSet<QString> &sourceFiles, - CppTools::CppModelManager::ProgressNotificationMode mode) -{ - Q_UNUSED(mode); - - return m_indexer->refreshSourceFiles(sourceFiles); -} - -CppTools::SymbolSearcher *ClangIndexingSupport::createSymbolSearcher(CppTools::SymbolSearcher::Parameters parameters, QSet<QString> fileNames) -{ - Q_UNUSED(parameters); - Q_UNUSED(fileNames) -// return new ClangSymbolSearcher(m_indexer, parameters, fileNames); - return 0; -} - -ClangIndexer::ClangIndexer() - : QObject(0) - , m_indexingSupport(new ClangIndexingSupport(this)) - , m_isLoadingSession(false) - , m_clangIndexer(new Indexer(this)) -{ - connect(m_clangIndexer, SIGNAL(indexingStarted(QFuture<void>,Internal::ProgressNotificationMode)), - this, SLOT(onIndexingStarted(QFuture<void>,Internal::ProgressNotificationMode))); - - QObject *session = ProjectExplorer::SessionManager::instance(); - - connect(session, SIGNAL(aboutToLoadSession(QString)), - this, SLOT(onAboutToLoadSession(QString))); - connect(session, SIGNAL(sessionLoaded(QString)), - this, SLOT(onSessionLoaded(QString))); - connect(session, SIGNAL(aboutToSaveSession()), - this, SLOT(onAboutToSaveSession())); -} - -ClangIndexer::~ClangIndexer() -{ - m_clangIndexer->cancel(true); -} - -CppTools::CppIndexingSupport *ClangIndexer::indexingSupport() -{ - return m_indexingSupport.data(); -} - -QFuture<void> ClangIndexer::refreshSourceFiles(const QSet<QString> &sourceFiles) -{ - typedef CppTools::ProjectPart ProjectPart; - CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance(); - - if (m_clangIndexer->isBusy()) - m_clangIndexer->cancel(true); - - foreach (const QString &file, sourceFiles) { - if (m_clangIndexer->isTracking(file)) - continue; // we get notified separately about open files. - const QList<ProjectPart::Ptr> &parts = modelManager->projectPart(file); - if (!parts.isEmpty()) - m_clangIndexer->addFile(file, parts.at(0)); - else - m_clangIndexer->addFile(file, ProjectPart::Ptr()); - } - - if (!m_isLoadingSession) - m_clangIndexer->regenerate(); - - return QFuture<void>(); -} - -void ClangIndexer::match(ClangSymbolSearcher *searcher) const -{ - m_clangIndexer->match(searcher); -} - -void ClangIndexer::onAboutToLoadSession(const QString &sessionName) -{ - m_isLoadingSession = true; - - if (sessionName == QLatin1String("default")) - return; - - QString path = Core::ICore::instance()->userResourcePath() + QLatin1String("/codemodel/"); - if (QFile::exists(path) || QDir().mkpath(path)) - m_clangIndexer->initialize(path + sessionName + QLatin1String(".qci")); -} - -void ClangIndexer::onSessionLoaded(QString) -{ - m_isLoadingSession = false; - m_clangIndexer->regenerate(); -} - -void ClangIndexer::onAboutToSaveSession() -{ - m_clangIndexer->finalize(); -} - -void ClangIndexer::indexNow(Unit::Ptr unit) -{ - typedef CppTools::ProjectPart ProjectPart; - - QString file = unit->fileName(); - CppTools::CppModelManager *mmi = CppTools::CppModelManager::instance(); - const QList<ProjectPart::Ptr> &parts = mmi->projectPart(file); - ProjectPart::Ptr part; - if (!parts.isEmpty()) - part = parts.at(0); - if (!m_isLoadingSession) - m_clangIndexer->runQuickIndexing(unit, part); -} - -void ClangIndexer::onIndexingStarted(QFuture<void> indexingFuture) -{ - Core::ProgressManager::addTask(indexingFuture, QCoreApplication::translate( - "ClangCodeModel::Internal::ClangIndexer", - "Parsing C/C++/ObjC Files"), - "ClangCodeMode.Task.Indexing"); -} diff --git a/src/plugins/clangcodemodel/clangindexer.h b/src/plugins/clangcodemodel/clangindexer.h deleted file mode 100644 index 08899a4ff4..0000000000 --- a/src/plugins/clangcodemodel/clangindexer.h +++ /dev/null @@ -1,99 +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 CLANGINDEXER_H -#define CLANGINDEXER_H - -#include "fastindexer.h" - -#include <cpptools/cppindexingsupport.h> - -#include <QObject> - -namespace ClangCodeModel { - -class Indexer; - -namespace Internal { - -typedef CppTools::CppModelManager::ProgressNotificationMode ProgressNotificationMode; -class ClangIndexer; -class ClangSymbolSearcher; - -class ClangIndexingSupport: public CppTools::CppIndexingSupport -{ -public: - ClangIndexingSupport(ClangIndexer *indexer); - virtual ~ClangIndexingSupport(); - - virtual QFuture<void> refreshSourceFiles( - const QSet<QString> &sourceFiles, - ProgressNotificationMode mode); - virtual CppTools::SymbolSearcher *createSymbolSearcher( - CppTools::SymbolSearcher::Parameters parameters, QSet<QString> fileNames); - -private: - ClangIndexer *m_indexer; -}; - -class ClangIndexer: public QObject, public FastIndexer -{ - Q_OBJECT - -public: - ClangIndexer(); - ~ClangIndexer(); - - CppTools::CppIndexingSupport *indexingSupport(); - - QFuture<void> refreshSourceFiles(const QSet<QString> &sourceFiles); - - void match(ClangSymbolSearcher *searcher) const; - - void indexNow(Unit::Ptr unit); - -public slots: - void onAboutToLoadSession(const QString &sessionName); - void onSessionLoaded(QString); - void onAboutToSaveSession(); - -private slots: - void onIndexingStarted(QFuture<void> indexingFuture); - -private: - QScopedPointer<ClangIndexingSupport> m_indexingSupport; - bool m_isLoadingSession; - Indexer *m_clangIndexer; -}; - -} // namespace Internal -} // namespace ClangCodeModel - -#endif // CLANGINDEXER_H diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index 2678064830..3b5384b20b 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -30,7 +30,7 @@ #include "clangmodelmanagersupport.h" -#include "constants.h" +#include "clangconstants.h" #include "clangeditordocumentprocessor.h" #include "clangutils.h" @@ -66,9 +66,14 @@ ModelManagerSupportClang::ModelManagerSupportClang() Core::EditorManager *editorManager = Core::EditorManager::instance(); connect(editorManager, &Core::EditorManager::currentEditorChanged, - this, &ModelManagerSupportClang::onCurrentEditorChanged); + this, &ModelManagerSupportClang::onCurrentEditorChanged, + Qt::QueuedConnection); connect(editorManager, &Core::EditorManager::editorOpened, - this, &ModelManagerSupportClang::onEditorOpened); + this, &ModelManagerSupportClang::onEditorOpened, + Qt::QueuedConnection); + connect(editorManager, &Core::EditorManager::editorsClosed, + this, &ModelManagerSupportClang::onEditorClosed, + Qt::QueuedConnection); CppTools::CppModelManager *modelManager = cppModelManager(); connect(modelManager, &CppTools::CppModelManager::abstractEditorSupportContentsUpdated, @@ -97,20 +102,9 @@ CppTools::BaseEditorDocumentProcessor *ModelManagerSupportClang::editorDocumentP return new ClangEditorDocumentProcessor(this, baseTextDocument); } -void ModelManagerSupportClang::onCurrentEditorChanged(Core::IEditor *newCurrent) +void ModelManagerSupportClang::onCurrentEditorChanged(Core::IEditor *) { - // If we switch away from a cpp editor, update the backend about - // the document's unsaved content. - if (m_previousCppEditor && m_previousCppEditor->document()->isModified()) { - m_ipcCommunicator.updateTranslationUnitFromCppEditorDocument( - m_previousCppEditor->document()->filePath().toString()); - } - - // Remember previous editor - if (newCurrent && cppModelManager()->isCppEditor(newCurrent)) - m_previousCppEditor = newCurrent; - else - m_previousCppEditor.clear(); + m_ipcCommunicator.updateTranslationUnitVisiblity(); } void ModelManagerSupportClang::connectTextDocumentToTranslationUnit(TextEditor::TextDocument *textDocument) @@ -181,6 +175,11 @@ void ModelManagerSupportClang::onEditorOpened(Core::IEditor *editor) } } +void ModelManagerSupportClang::onEditorClosed(const QList<Core::IEditor *> &) +{ + m_ipcCommunicator.updateTranslationUnitVisiblity(); +} + void ModelManagerSupportClang::onCppDocumentAboutToReloadOnTranslationUnit() { TextEditor::TextDocument *textDocument = qobject_cast<TextEditor::TextDocument *>(sender()); @@ -193,7 +192,7 @@ void ModelManagerSupportClang::onCppDocumentReloadFinishedOnTranslationUnit(bool if (success) { TextEditor::TextDocument *textDocument = qobject_cast<TextEditor::TextDocument *>(sender()); connectToTextDocumentContentsChangedForTranslationUnit(textDocument); - m_ipcCommunicator.requestDiagnostics(textDocument); + m_ipcCommunicator.updateTranslationUnitWithRevisionCheck(textDocument); } } @@ -342,7 +341,7 @@ void ModelManagerSupportClang::unregisterTranslationUnitsWithProjectParts( { const auto processors = clangProcessorsWithProjectParts(projectPartIds); foreach (ClangEditorDocumentProcessor *processor, processors) { - m_ipcCommunicator.unregisterTranslationUnitsForEditor({processor->fileContainer()}); + m_ipcCommunicator.unregisterTranslationUnitsForEditor({processor->fileContainerWithArguments()}); processor->clearProjectPart(); processor->run(); } diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.h b/src/plugins/clangcodemodel/clangmodelmanagersupport.h index 54478a6ee5..597dfff388 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.h +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.h @@ -71,6 +71,7 @@ public: private: void onEditorOpened(Core::IEditor *editor); + void onEditorClosed(const QList<Core::IEditor *> &editors); void onCurrentEditorChanged(Core::IEditor *newCurrent); void onCppDocumentAboutToReloadOnTranslationUnit(); void onCppDocumentReloadFinishedOnTranslationUnit(bool success); @@ -103,7 +104,6 @@ private: private: IpcCommunicator m_ipcCommunicator; ClangCompletionAssistProvider m_completionAssistProvider; - QPointer<Core::IEditor> m_previousCppEditor; }; class ModelManagerSupportProviderClang : public CppTools::ModelManagerSupportProvider diff --git a/src/plugins/clangcodemodel/clangprojectsettings.h b/src/plugins/clangcodemodel/clangprojectsettings.h index 1f38120b70..a5956d33df 100644 --- a/src/plugins/clangcodemodel/clangprojectsettings.h +++ b/src/plugins/clangcodemodel/clangprojectsettings.h @@ -31,8 +31,6 @@ #ifndef CLANGPROJECTSETTINGS_H #define CLANGPROJECTSETTINGS_H -#include "clang_global.h" - #include <projectexplorer/project.h> #include <QObject> @@ -40,7 +38,7 @@ namespace ClangCodeModel { -class CLANG_EXPORT ClangProjectSettings: public QObject +class ClangProjectSettings: public QObject { Q_OBJECT diff --git a/src/plugins/clangcodemodel/clangprojectsettingspropertiespage.cpp b/src/plugins/clangcodemodel/clangprojectsettingspropertiespage.cpp index 5a08c1a0ea..3fb2e797f0 100644 --- a/src/plugins/clangcodemodel/clangprojectsettingspropertiespage.cpp +++ b/src/plugins/clangcodemodel/clangprojectsettingspropertiespage.cpp @@ -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()); } diff --git a/src/plugins/clangcodemodel/clangprojectsettingspropertiespage.h b/src/plugins/clangcodemodel/clangprojectsettingspropertiespage.h index 0e1f87f54a..f77ef34232 100644 --- a/src/plugins/clangcodemodel/clangprojectsettingspropertiespage.h +++ b/src/plugins/clangcodemodel/clangprojectsettingspropertiespage.h @@ -33,10 +33,8 @@ #include "ui_clangprojectsettingspropertiespage.h" -#include <QString> - namespace ProjectExplorer { - class Project; +class Project; } namespace ClangCodeModel { @@ -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; diff --git a/src/plugins/clangcodemodel/clangprojectsettingspropertiespage.ui b/src/plugins/clangcodemodel/clangprojectsettingspropertiespage.ui index 66dcf45c5b..8b2fae3a6f 100644 --- a/src/plugins/clangcodemodel/clangprojectsettingspropertiespage.ui +++ b/src/plugins/clangcodemodel/clangprojectsettingspropertiespage.ui @@ -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> diff --git a/src/plugins/clangcodemodel/clangtextmark.cpp b/src/plugins/clangcodemodel/clangtextmark.cpp index 38b7228795..01fafd9e24 100644 --- a/src/plugins/clangcodemodel/clangtextmark.cpp +++ b/src/plugins/clangcodemodel/clangtextmark.cpp @@ -30,7 +30,7 @@ #include "clangtextmark.h" -#include "constants.h" +#include "clangconstants.h" #include <coreplugin/coreicons.h> diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp index 28c223d80a..a3c693b126 100644 --- a/src/plugins/clangcodemodel/clangutils.cpp +++ b/src/plugins/clangcodemodel/clangutils.cpp @@ -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 diff --git a/src/plugins/clangcodemodel/clangutils.h b/src/plugins/clangcodemodel/clangutils.h index 11d8e9db11..7bce88179d 100644 --- a/src/plugins/clangcodemodel/clangutils.h +++ b/src/plugins/clangcodemodel/clangutils.h @@ -31,10 +31,7 @@ #ifndef CPPTOOLS_CLANGUTILS_H #define CPPTOOLS_CLANGUTILS_H -#include "clang_global.h" -#include "utils.h" - -#include <cpptools/cppmodelmanager.h> +#include <cpptools/cppprojects.h> #include <QLoggingCategory> @@ -43,10 +40,6 @@ namespace Utils { Q_DECLARE_LOGGING_CATEGORY(verboseRunLog) -ClangCodeModel::Internal::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, diff --git a/src/plugins/clangcodemodel/constants.h b/src/plugins/clangcodemodel/constants.h deleted file mode 100644 index 7b8a4e829c..0000000000 --- a/src/plugins/clangcodemodel/constants.h +++ /dev/null @@ -1,65 +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 CONSTANTS_H -#define CONSTANTS_H - -#include <QtCore/QLatin1Char> - -namespace ClangCodeModel { -namespace Constants { - -static const QLatin1Char kLParen('('); -static const QLatin1Char kRParen(')'); -static const QLatin1Char kLBrace('{'); -static const QLatin1Char kRBrace('}'); -static const QLatin1Char kLBracket('['); -static const QLatin1Char kRBracket(']'); -static const QLatin1Char kLABracket('<'); -static const QLatin1Char kRABracket('>'); -static const QLatin1Char kSemiColon(';'); -static const QLatin1Char kPound('#'); -static const QLatin1Char kColon(':'); -static const QLatin1Char kExclamation('!'); -static const QLatin1Char kSpace(' '); -static const QLatin1Char kSlash('/'); -static const QLatin1Char kStar('*'); -static const QLatin1Char kDoubleQuote('"'); -static const QLatin1Char kNewLine('\n'); -static const QLatin1Char kHorizontalTab('\t'); - -const char CLANG_MODELMANAGERSUPPORT_ID[] = "ClangCodeModel.ClangCodeModel"; -const char CLANG_ERROR[] = "Clang.Error"; -const char CLANG_WARNING[] = "Clang.Warning"; - -} -} - -#endif // CONSTANTS_H diff --git a/src/plugins/clangcodemodel/cppcreatemarkers.cpp b/src/plugins/clangcodemodel/cppcreatemarkers.cpp deleted file mode 100644 index a7518b355c..0000000000 --- a/src/plugins/clangcodemodel/cppcreatemarkers.cpp +++ /dev/null @@ -1,135 +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 "clangutils.h" -#include "cppcreatemarkers.h" - -#include <cplusplus/CppDocument.h> -#include <utils/executeondestruction.h> -#include <utils/runextensions.h> - -#include <QCoreApplication> -#include <QLoggingCategory> -#include <QMutexLocker> -#include <QThreadPool> - -#include <QDebug> - -using namespace ClangCodeModel; -using namespace ClangCodeModel::Internal; -using namespace CppTools; - -static Q_LOGGING_CATEGORY(log, "qtc.clangcodemodel.createmarkers") - -CreateMarkers *CreateMarkers::create(SemanticMarker::Ptr semanticMarker, - const QString &fileName, - unsigned firstLine, unsigned lastLine) -{ - if (semanticMarker.isNull()) - return 0; - else - return new CreateMarkers(semanticMarker, fileName, firstLine, lastLine); -} - -CreateMarkers::CreateMarkers(SemanticMarker::Ptr semanticMarker, - const QString &fileName, - unsigned firstLine, unsigned lastLine) - : m_marker(semanticMarker) - , m_fileName(fileName) - , m_firstLine(firstLine) - , m_lastLine(lastLine) -{ - Q_ASSERT(!semanticMarker.isNull()); - - m_flushRequested = false; - m_flushLine = 0; -} - -CreateMarkers::~CreateMarkers() -{ } - -void CreateMarkers::run() -{ - QMutexLocker lock(m_marker->mutex()); - - ::Utils::ExecuteOnDestruction reportFinishedOnDestruction([this]() { reportFinished(); }); - - if (isCanceled()) - return; - - qCDebug(log) << "Creating markers from" << m_firstLine << "to" << m_lastLine - << "of" << m_fileName; - QTime t; t.start(); - - m_usages.clear(); - - if (isCanceled()) - return; - - const QList<ClangCodeModel::SourceMarker> markers - = m_marker->sourceMarkersInRange(m_firstLine, m_lastLine); - foreach (const ClangCodeModel::SourceMarker &m, markers) - addUse(SourceMarker(m.location().line(), m.location().column(), m.length(), m.kind())); - - if (isCanceled()) - return; - - flush(); - - qCDebug(log) << "Creating markers took" << t.elapsed() << "ms in total."; -} - -void CreateMarkers::addUse(const SourceMarker &marker) -{ -// if (! enclosingFunctionDefinition()) { - if (m_usages.size() >= 100) { - if (m_flushRequested && marker.line != m_flushLine) - flush(); - else if (! m_flushRequested) { - m_flushRequested = true; - m_flushLine = marker.line; - } - } -// } - - m_usages.append(marker); -} - -void CreateMarkers::flush() -{ - m_flushRequested = false; - m_flushLine = 0; - - if (m_usages.isEmpty()) - return; - - reportResults(m_usages); - m_usages.clear(); -} diff --git a/src/plugins/clangcodemodel/cppcreatemarkers.h b/src/plugins/clangcodemodel/cppcreatemarkers.h deleted file mode 100644 index 3210e1fc96..0000000000 --- a/src/plugins/clangcodemodel/cppcreatemarkers.h +++ /dev/null @@ -1,94 +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 CPPCREATEMARKERS_H -#define CPPCREATEMARKERS_H - -#include "fastindexer.h" -#include "sourcemarker.h" -#include "semanticmarker.h" -#include "pchinfo.h" - -#include <texteditor/semantichighlighter.h> - -#include <QFuture> -#include <QtConcurrentRun> - -namespace ClangCodeModel { - -class CreateMarkers: - public QObject, - public QRunnable, - public QFutureInterface<TextEditor::HighlightingResult> -{ - Q_OBJECT - Q_DISABLE_COPY(CreateMarkers) - -public: - virtual ~CreateMarkers(); - - virtual void run(); - - typedef TextEditor::HighlightingResult SourceMarker; - - typedef QFuture<SourceMarker> Future; - - Future start() - { - this->setRunnable(this); - this->reportStarted(); - Future future = this->future(); - QThreadPool::globalInstance()->start(this, QThread::LowestPriority); - return future; - } - - static CreateMarkers *create(ClangCodeModel::SemanticMarker::Ptr semanticMarker, - const QString &fileName, unsigned firstLine, unsigned lastLine); - - void addUse(const SourceMarker &marker); - void flush(); - -protected: - CreateMarkers(ClangCodeModel::SemanticMarker::Ptr semanticMarker, - const QString &fileName, unsigned firstLine, unsigned lastLine); - -private: - ClangCodeModel::SemanticMarker::Ptr m_marker; - QString m_fileName; - unsigned m_firstLine; - unsigned m_lastLine; - QVector<SourceMarker> m_usages; - bool m_flushRequested; - unsigned m_flushLine; -}; - -} // namespace ClangCodeModel - -#endif // CPPCREATEMARKERS_H diff --git a/src/plugins/clangcodemodel/cxprettyprinter.cpp b/src/plugins/clangcodemodel/cxprettyprinter.cpp deleted file mode 100644 index 0d57f01174..0000000000 --- a/src/plugins/clangcodemodel/cxprettyprinter.cpp +++ /dev/null @@ -1,551 +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 "cxprettyprinter.h" -#include "utils_p.h" -#include "cxraii.h" -#include <QStringList> - -using namespace ClangCodeModel; -using namespace ClangCodeModel::Internal; - -CXPrettyPrinter::CXPrettyPrinter() - : m_indent(0) -{ -} - -QString CXPrettyPrinter::toString(CXCompletionChunkKind kind) const -{ - switch (kind) { - case CXCompletionChunk_Optional: - return QLatin1String("Optional"); - case CXCompletionChunk_TypedText: - return QLatin1String("TypedText"); - case CXCompletionChunk_Text: - return QLatin1String("Text"); - case CXCompletionChunk_Placeholder: - return QLatin1String("Placeholder"); - case CXCompletionChunk_Informative: - return QLatin1String("Informative"); - case CXCompletionChunk_CurrentParameter: - return QLatin1String("CurrentParameter"); - case CXCompletionChunk_LeftParen: - return QLatin1String("LeftParen"); - case CXCompletionChunk_RightParen: - return QLatin1String("RightParen"); - case CXCompletionChunk_LeftBracket: - return QLatin1String("LeftBracket"); - case CXCompletionChunk_RightBracket: - return QLatin1String("RightBracket"); - case CXCompletionChunk_LeftBrace: - return QLatin1String("LeftBrace"); - case CXCompletionChunk_RightBrace: - return QLatin1String("RightBrace"); - case CXCompletionChunk_LeftAngle: - return QLatin1String("LeftAngle"); - case CXCompletionChunk_RightAngle: - return QLatin1String("RightAngle"); - case CXCompletionChunk_Comma: - return QLatin1String("Comma"); - case CXCompletionChunk_ResultType: - return QLatin1String("ResultType"); - case CXCompletionChunk_Colon: - return QLatin1String("Colon"); - case CXCompletionChunk_SemiColon: - return QLatin1String("SemiColon"); - case CXCompletionChunk_Equal: - return QLatin1String("Equal"); - case CXCompletionChunk_HorizontalSpace: - return QLatin1String("HorizontalSpace"); - case CXCompletionChunk_VerticalSpace: - return QLatin1String("VerticalSpace"); - default: - return QLatin1String("<UNKNOWN>"); - } -} - -QString CXPrettyPrinter::toString(CXAvailabilityKind kind) const -{ - switch (kind) { - case CXAvailability_Available: - return QLatin1String("Available"); - case CXAvailability_Deprecated: - return QLatin1String("Deprecated"); - case CXAvailability_NotAccessible: - return QLatin1String("NotAccessible"); - case CXAvailability_NotAvailable: - return QLatin1String("NotAvailable"); - default: - return QLatin1String("<UNKNOWN>"); - } -} - -QString CXPrettyPrinter::toString(CXCursorKind kind) const -{ - return getQString(clang_getCursorKindSpelling(kind)); -} - -QString CXPrettyPrinter::toString(CXDiagnosticSeverity severity) const -{ - switch (severity) - { - case CXDiagnostic_Ignored: - return QLatin1String("Ignored"); - case CXDiagnostic_Note: - return QLatin1String("Note"); - case CXDiagnostic_Warning: - return QLatin1String("Warning"); - case CXDiagnostic_Error: - return QLatin1String("Error"); - case CXDiagnostic_Fatal: - return QLatin1String("Fatal"); - default: - return QLatin1String("<UNKNOWN>"); - } -} - -QString CXPrettyPrinter::jsonForCompletionMeta(CXCodeCompleteResults *results) -{ - QString json; - m_printed.swap(json); - m_indent = 0; - - m_printed += QLatin1String("CXCodeCompleteResults {"); - m_indent += 4; - - CXCursorKind containerKind = clang_codeCompleteGetContainerKind(results, NULL); - writeLineEnd(); - m_printed += QLatin1String("'container CursorKind': "); - m_printed += toString(containerKind); - m_printed += QLatin1Char(','); - - QString containerUSR(Internal::getQString(clang_codeCompleteGetContainerUSR(results))); - if (!containerUSR.isEmpty()) { - writeLineEnd(); - m_printed += QLatin1String("'container USR': "); - m_printed += containerUSR; - m_printed += QLatin1Char(','); - } - - QString objCSelector(Internal::getQString(clang_codeCompleteGetObjCSelector(results))); - if (!objCSelector.isEmpty()) { - writeLineEnd(); - m_printed += QLatin1String("'Objective-C selector': "); - m_printed += objCSelector; - m_printed += QLatin1Char(','); - } - - writeLineEnd(); - m_printed += QLatin1String("'contexts': ["); - m_indent += 4; - writeCompletionContexts(results); - m_indent -= 4; - writeLineEnd(); - m_printed += QLatin1Char(']'); - - m_indent -= 4; - writeLineEnd(); - m_printed += QLatin1Char('}'); - - m_printed.swap(json); - return json; -} - -QString CXPrettyPrinter::jsonForCompletionString(const CXCompletionString &string) -{ - QString json; - m_printed.swap(json); - m_indent = 0; - - m_printed += QLatin1String("CXCompletionString: "); - writeCompletionStringJson(string); - - m_printed.swap(json); - return json; -} - -QString CXPrettyPrinter::jsonForCompletion(const CXCompletionResult &result) -{ - QString json; - m_printed.swap(json); - m_indent = 4; - - m_printed += QLatin1String("CXCompletionResult: {\n" - " CompletionString: "); - writeCompletionStringJson(result.CompletionString); - m_printed += QLatin1Char('\n'); - - m_printed += QLatin1String(" CursorKind: "); - m_printed += toString(result.CursorKind); - m_printed += QLatin1String(";\n}"); - - m_printed.swap(json); - return json; -} - -/** - * @brief CXPrettyPrinter::jsonForDiagnsotic - * @param diagnostic - * @return - * - * List of used clang-c API calls: - * CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic D); - * CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic); - * CXString clang_getDiagnosticOption(CXDiagnostic Diag, - * CXString *Disable); - * unsigned clang_getDiagnosticCategory(CXDiagnostic); - * CXString clang_getDiagnosticCategoryText(CXDiagnostic); - * unsigned clang_getDiagnosticNumRanges(CXDiagnostic); - * CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diagnostic, - * unsigned Range); - * unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diagnostic); - * CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic, - * unsigned FixIt, - * CXSourceRange *ReplacementRange); - */ -QString CXPrettyPrinter::jsonForDiagnsotic(const CXDiagnostic &diagnostic) -{ - QString json; - m_printed.swap(json); - m_indent = 0; - - m_printed += QLatin1String("CXDiagnostic: "); - writeDiagnosticJson(diagnostic); - - m_printed.swap(json); - return json; -} - -void CXPrettyPrinter::writeCompletionContexts(CXCodeCompleteResults *results) -{ - quint64 contexts = clang_codeCompleteGetContexts(results); - QStringList lines; - - if (contexts & CXCompletionContext_AnyType) - lines << QLatin1String("'any type'"); - if (contexts & CXCompletionContext_AnyValue) - lines << QLatin1String("'any value'"); - if (contexts & CXCompletionContext_ObjCObjectValue) - lines << QLatin1String("'Objective-C object'"); - if (contexts & CXCompletionContext_ObjCSelectorValue) - lines << QLatin1String("'Objective-C selector'"); - if (contexts & CXCompletionContext_CXXClassTypeValue) - lines << QLatin1String("'C++ class'"); - if (contexts & CXCompletionContext_DotMemberAccess) - lines << QLatin1String("'. member access'"); - if (contexts & CXCompletionContext_ArrowMemberAccess) - lines << QLatin1String("'-> member access'"); - if (contexts & CXCompletionContext_ObjCPropertyAccess) - lines << QLatin1String("'. Objective-C property access'"); - if (contexts & CXCompletionContext_EnumTag) - lines << QLatin1String("'enum tag'"); - if (contexts & CXCompletionContext_UnionTag) - lines << QLatin1String("'union tag'"); - if (contexts & CXCompletionContext_StructTag) - lines << QLatin1String("'struct tag'"); - if (contexts & CXCompletionContext_ClassTag) - lines << QLatin1String("'C++ class tag'"); - if (contexts & CXCompletionContext_Namespace) - lines << QLatin1String("'namespace tag'"); - if (contexts & CXCompletionContext_NestedNameSpecifier) - lines << QLatin1String("'C++ nested name specifier'"); - if (contexts & CXCompletionContext_ObjCInterface) - lines << QLatin1String("'Objective-C interface'"); - if (contexts & CXCompletionContext_ObjCProtocol) - lines << QLatin1String("'Objective-C protocol'"); - if (contexts & CXCompletionContext_ObjCCategory) - lines << QLatin1String("'Objective-C category'"); - if (contexts & CXCompletionContext_ObjCInstanceMessage) - lines << QLatin1String("'Objective-C instance message'"); - if (contexts & CXCompletionContext_ObjCClassMessage) - lines << QLatin1String("'Objective-C class message'"); - if (contexts & CXCompletionContext_ObjCSelectorName) - lines << QLatin1String("'Objective-C selector name'"); - if (contexts & CXCompletionContext_MacroName) - lines << QLatin1String("'macro name'"); - if (contexts & CXCompletionContext_NaturalLanguage) - lines << QLatin1String("'natural language'"); - - foreach (const QString &line, lines) { - writeLineEnd(); - m_printed += line + QLatin1Char(','); - } -} - -void CXPrettyPrinter::writeCompletionStringJson(const CXCompletionString &string) -{ - m_printed += QLatin1Char('{'); - writeLineEnd(); - - // availability - m_printed += QLatin1String("availability: "); - m_printed += toString(clang_getCompletionAvailability(string)); - m_printed += QLatin1Char(';'); - writeLineEnd(); - - // priority - m_printed += QLatin1String("priority: "); - m_printed += QString::number(clang_getCompletionPriority(string)); - m_printed += QLatin1Char(';'); - writeLineEnd(); - - // parent - m_printed += QLatin1String("parent: \'"); - m_printed += getQString(clang_getCompletionParent(string, NULL)); - m_printed += QLatin1String("\';"); - writeLineEnd(); - - // chunks - m_printed += QLatin1String("chunks: ["); - m_indent += 4; - unsigned numChunks = clang_getNumCompletionChunks(string); - for (unsigned i = 0; i < numChunks; ++i) { - writeLineEnd(); - writeCompletionChunkJson(string, i); - } - m_indent -= 4; - writeLineEnd(); - m_printed += QLatin1Char(']'); - writeLineEnd(); - - // annotation - m_printed += QLatin1String("annotations: ["); - m_indent += 4; - unsigned numAnns = clang_getCompletionNumAnnotations(string); - for (unsigned i = 0; i < numAnns; ++i) { - writeLineEnd(); - writeCompletionAnnotationJson(string, i); - } - m_indent -= 4; - writeLineEnd(); - m_printed += QLatin1Char(']'); - writeLineEnd(); - - m_printed += QLatin1Char('}'); -} - -void CXPrettyPrinter::writeCompletionChunkJson(const CXCompletionString &string, unsigned i) -{ - QString text = getQString(clang_getCompletionChunkText(string, i)); - QString kind = toString(clang_getCompletionChunkKind(string, i)); - CXCompletionString optional = clang_getCompletionChunkCompletionString(string, i); - - m_printed += kind; - m_printed += QLatin1String(": "); - if (!text.isEmpty()) { - m_printed += QLatin1Char('\''); - m_printed += text; - m_printed += QLatin1Char('\''); - } - if (optional != NULL) { - if (!text.isEmpty()) - m_printed += QLatin1String(", "); - m_indent += 4; - writeCompletionStringJson(optional); - m_indent -= 4; - } -} - -void CXPrettyPrinter::writeCompletionAnnotationJson(const CXCompletionString &string, unsigned i) -{ - m_printed += QLatin1Char('\''); - m_printed += getQString(clang_getCompletionAnnotation(string, i)); - m_printed += QLatin1Char('\''); -} - -void CXPrettyPrinter::writeDiagnosticJson(const CXDiagnostic &diag) -{ - m_printed += QLatin1Char('{'); - m_indent += 4; - writeLineEnd(); - - // message - m_printed += QLatin1Char('\''); - m_printed += getQString(clang_formatDiagnostic(diag, /*options*/ 0)); - m_printed += QLatin1Char('\''); - writeLineEnd(); - - // severity - m_printed += QLatin1String("severity: "); - m_printed += toString(clang_getDiagnosticSeverity(diag)); - writeLineEnd(); - - // location - m_printed += QLatin1String("location: "); - writeLocationJson(clang_getDiagnosticLocation(diag)); - writeLineEnd(); - - // fix-its - unsigned numFixIts = clang_getDiagnosticNumFixIts(diag); - if (numFixIts > 0) { - m_printed += QLatin1String("FixIts: ["); - writeLineEnd(); - for (unsigned i = 0; i < numFixIts; ++i) { - writeFixItJson(diag, i); - writeLineEnd(); - } - m_printed += QLatin1Char(']'); - writeLineEnd(); - } - - // clang CLI options - CXString cxDisabler; - QString enabler = getQString(clang_getDiagnosticOption(diag, &cxDisabler)); - QString disabler = getQString(cxDisabler); - if (!enabler.isEmpty()) { - m_printed += QLatin1String("enabledBy: \'"); - m_printed += enabler; - m_printed += QLatin1String("';"); - writeLineEnd(); - } - if (!disabler.isEmpty()) { - m_printed += QLatin1String("disabledBy: \'"); - m_printed += disabler; - m_printed += QLatin1String("';"); - writeLineEnd(); - } - - // diagnostic category - m_printed += QLatin1String("category: \'"); - m_printed += getQString(clang_getDiagnosticCategoryText(diag)); - m_printed += QLatin1String("';"); - - // ranges - unsigned numRanges = clang_getDiagnosticNumRanges(diag); - if (numRanges > 0) { - writeLineEnd(); - m_printed += QLatin1String("ranges: ["); - m_indent += 4; - for (unsigned i = 0; i < numRanges; ++i) { - writeLineEnd(); - writeRangeJson(clang_getDiagnosticRange(diag, i)); - } - m_indent -= 4; - writeLineEnd(); - m_printed += QLatin1Char(']'); - } - - // children - CXDiagnosticSet set(clang_getChildDiagnostics(diag)); - unsigned numChildren = clang_getNumDiagnosticsInSet(set); - if (numChildren > 0) { - writeLineEnd(); - m_printed += QLatin1String("children: ["); - m_indent += 4; - for (unsigned i = 0; i < numChildren; ++i) { - writeLineEnd(); - ScopedCXDiagnostic child(clang_getDiagnosticInSet(set, i)); - writeDiagnosticJson(child); - } - m_indent -= 4; - writeLineEnd(); - m_printed += QLatin1Char(']'); - } - - m_indent -= 4; - writeLineEnd(); - m_printed += QLatin1Char('}'); -} - -void CXPrettyPrinter::writeFixItJson(const CXDiagnostic &diag, unsigned i) -{ - CXSourceRange range; // half-open range [a, b) - QString text = getQString(clang_getDiagnosticFixIt(diag, i, &range)); - - m_printed += QLatin1String("{ newText: "); - m_printed += QLatin1String("\'"); - m_printed += text; - m_printed += QLatin1String("\', range: "); - writeRangeJson(range); - m_printed += QLatin1Char('}'); -} - -void CXPrettyPrinter::writeRangeJson(const CXSourceRange &range) -{ - SourceLocation start = getSpellingLocation(clang_getRangeStart(range)); - SourceLocation end = getSpellingLocation(clang_getRangeEnd(range)); - - m_printed += QLatin1Char('{'); - m_indent += 4; - writeLineEnd(); - - m_printed += QLatin1String("file: \'"); - m_printed += start.fileName(); - m_printed += QLatin1String("\',"); - writeLineEnd(); - - m_printed += QLatin1String("from: {"); - m_printed += QString::number(start.line()); - m_printed += QLatin1String(", "); - m_printed += QString::number(start.column()); - m_printed += QLatin1String("},"); - - m_printed += QLatin1String("to: {"); - m_printed += QString::number(end.line()); - m_printed += QLatin1String(", "); - m_printed += QString::number(end.column()); - m_printed += QLatin1Char('}'); - - m_indent -= 4; - writeLineEnd(); - m_printed += QLatin1Char('}'); -} - -void CXPrettyPrinter::writeLocationJson(const CXSourceLocation &location) -{ - SourceLocation loc = getSpellingLocation(location); - m_printed += QLatin1Char('{'); - m_indent += 4; - writeLineEnd(); - - m_printed += QLatin1String("file: \'"); - m_printed += loc.fileName(); - m_printed += QLatin1String("\',"); - writeLineEnd(); - - m_printed += QLatin1String("line: "); - m_printed += QString::number(loc.line()); - m_printed += QLatin1Char(','); - writeLineEnd(); - - m_printed += QLatin1String("column: "); - m_printed += QString::number(loc.column()); - - m_indent -= 4; - writeLineEnd(); - m_printed += QLatin1Char('}'); -} - -void CXPrettyPrinter::writeLineEnd() -{ - m_printed += QLatin1Char('\n'); - for (int i = 0; i < m_indent; ++i) - m_printed += QLatin1Char(' '); -} diff --git a/src/plugins/clangcodemodel/cxprettyprinter.h b/src/plugins/clangcodemodel/cxprettyprinter.h deleted file mode 100644 index 40f61be9f9..0000000000 --- a/src/plugins/clangcodemodel/cxprettyprinter.h +++ /dev/null @@ -1,76 +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 CXPRETTYPRINTER_H -#define CXPRETTYPRINTER_H - -#include <clang-c/Index.h> -#include <QString> - -namespace ClangCodeModel { -namespace Internal { - -class CXPrettyPrinter -{ -public: - CXPrettyPrinter(); - - QString toString(CXCompletionChunkKind kind) const; - QString toString(CXAvailabilityKind kind) const; - QString toString(CXCursorKind kind) const; - QString toString(CXDiagnosticSeverity severity) const; - - QString jsonForCompletionMeta(CXCodeCompleteResults *results); - QString jsonForCompletionString(const CXCompletionString &string); - QString jsonForCompletion(const CXCompletionResult &result); - QString jsonForDiagnsotic(const CXDiagnostic &diagnostic); - -private: - int m_indent; - QString m_printed; - - void writeCompletionContexts(CXCodeCompleteResults *results); - void writeCompletionStringJson(const CXCompletionString &string); - void writeCompletionChunkJson(const CXCompletionString &string, unsigned i); - void writeCompletionAnnotationJson(const CXCompletionString &string, unsigned i); - - void writeDiagnosticJson(const CXDiagnostic &diag); - void writeFixItJson(const CXDiagnostic &diag, unsigned i); - - void writeRangeJson(const CXSourceRange &range); - void writeLocationJson(const CXSourceLocation &location); - - void writeLineEnd(); -}; - -} // namespace Internal -} // namespace ClangCodeModel - -#endif // CXPRETTYPRINTER_H diff --git a/src/plugins/clangcodemodel/cxraii.h b/src/plugins/clangcodemodel/cxraii.h deleted file mode 100644 index f21bb454fd..0000000000 --- a/src/plugins/clangcodemodel/cxraii.h +++ /dev/null @@ -1,146 +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 CXRAII_H -#define CXRAII_H - -#include <clang-c/Index.h> - -// Simple RAII types for their CX correspondings - -namespace ClangCodeModel { -namespace Internal { - -template <class CXType_T> -struct ScopedCXType -{ -protected: - typedef void (*DisposeFunction)(CXType_T); - - ScopedCXType(DisposeFunction f) - : m_cx(0), m_disposeFunction(f) - {} - ScopedCXType(const CXType_T &cx, DisposeFunction f) - : m_cx(cx) , m_disposeFunction(f) - {} - -public: - ~ScopedCXType() - { - dispose(); - } - - operator CXType_T() const { return m_cx; } - bool operator!() const { return !m_cx; } - bool isNull() const { return !m_cx; } - void reset(const CXType_T &cx) - { - dispose(); - m_cx = cx; - } - -private: - ScopedCXType(const ScopedCXType &); - const ScopedCXType &operator=(const ScopedCXType &); - - void dispose() - { - if (m_cx) - m_disposeFunction(m_cx); - } - - CXType_T m_cx; - DisposeFunction m_disposeFunction; -}; - -struct ScopedCXIndex : ScopedCXType<CXIndex> -{ - ScopedCXIndex() - : ScopedCXType<CXIndex>(&clang_disposeIndex) - {} - ScopedCXIndex(const CXIndex &index) - : ScopedCXType<CXIndex>(index, &clang_disposeIndex) - {} -}; - -struct ScopedCXTranslationUnit : ScopedCXType<CXTranslationUnit> -{ - ScopedCXTranslationUnit() - : ScopedCXType<CXTranslationUnit>(&clang_disposeTranslationUnit) - {} - ScopedCXTranslationUnit(const CXTranslationUnit &unit) - : ScopedCXType<CXTranslationUnit>(unit, &clang_disposeTranslationUnit) - {} -}; - -struct ScopedCXDiagnostic : ScopedCXType<CXDiagnostic> -{ - ScopedCXDiagnostic() - : ScopedCXType<CXDiagnostic>(&clang_disposeDiagnostic) - {} - ScopedCXDiagnostic(const CXDiagnostic &diagnostic) - : ScopedCXType<CXDiagnostic>(diagnostic, &clang_disposeDiagnostic) - {} -}; - -struct ScopedCXDiagnosticSet : ScopedCXType<CXDiagnostic> -{ - ScopedCXDiagnosticSet() - : ScopedCXType<CXDiagnosticSet>(&clang_disposeDiagnosticSet) - {} - ScopedCXDiagnosticSet(const CXDiagnostic &diagnostic) - : ScopedCXType<CXDiagnosticSet>(diagnostic, &clang_disposeDiagnosticSet) - {} -}; - -struct ScopedCXCodeCompleteResults : ScopedCXType<CXCodeCompleteResults*> -{ - ScopedCXCodeCompleteResults() - : ScopedCXType<CXCodeCompleteResults*>(&clang_disposeCodeCompleteResults) - {} - ScopedCXCodeCompleteResults(CXCodeCompleteResults *results) - : ScopedCXType<CXCodeCompleteResults*>(results, &clang_disposeCodeCompleteResults) - {} - - unsigned size() const - { - return static_cast<CXCodeCompleteResults *>(*this)->NumResults; - } - - const CXCompletionResult &completionAt(unsigned i) - { - return static_cast<CXCodeCompleteResults *>(*this)->Results[i]; - } -}; - -} // Internal -} // ClangCodeModel - -#endif // CXRAII_H diff --git a/src/plugins/clangcodemodel/dependencygraph.cpp b/src/plugins/clangcodemodel/dependencygraph.cpp deleted file mode 100644 index 6d33ab7b5b..0000000000 --- a/src/plugins/clangcodemodel/dependencygraph.cpp +++ /dev/null @@ -1,209 +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 "dependencygraph.h" - -#include <QtCore/QtConcurrentRun> - -using namespace ClangCodeModel; -using namespace Internal; - -DependencyGraph::DependencyGraph() -{ - m_includeTracker.setResolutionMode(IncludeTracker::EveryMatchResolution); -} - -DependencyGraph::~DependencyGraph() -{ - discard(); -} - -void DependencyGraph::cancel() -{ - if (m_computeWatcher.isRunning()) { - m_computeWatcher.cancel(); - m_computeWatcher.waitForFinished(); - } -} - -void DependencyGraph::addFile(const QString &fileName, const QStringList &compilationOptions) -{ - cancel(); - - m_files.append(qMakePair(fileName, compilationOptions)); -} - -QFuture<void> DependencyGraph::compute() -{ - QFuture<void> future = QtConcurrent::run(this, &DependencyGraph::computeCore); - m_computeWatcher.setFuture(future); - return future; -} - -void DependencyGraph::computeCore() -{ - for (int i = 0; i < m_files.size(); ++i) { - if (m_computeWatcher.isCanceled()) - break; - - const QPair<QString, QStringList> &p = m_files.at(i); - const QString ¤tFile = p.first; - const QStringList &options = p.second; - const QPair<bool, NodeRefSetIt> &v = findVertex(currentFile); - if (!v.first) - processIncludes(insertVertex(currentFile), options); - } - - emit dependencyGraphAvailable(); -} - -void DependencyGraph::processIncludes(NodeRefSetIt currentIt, - const QStringList &compilationOptions) -{ - const QString ¤tFile = currentIt.key(); - const QStringList &includes = m_includeTracker.directIncludes(currentFile, compilationOptions); - foreach (const QString &include, includes) { - if (m_computeWatcher.isCanceled()) - return; - - QPair<bool, NodeRefSetIt> v = findVertex(include); - if (!v.first) { - v.second = insertVertex(include); - processIncludes(v.second, compilationOptions); - } - insertEdge(currentIt, v.second); - } -} - -namespace { - -struct SimpleVisitor -{ - bool acceptFile(const QString &fileName) - { - m_allFiles.append(fileName); - return false; - } - - QStringList m_allFiles; -}; - -} - -QStringList DependencyGraph::collectDependencies(const QString &referenceFile, - DependencyRole role) const -{ - SimpleVisitor visitor; - collectDependencies(referenceFile, role, &visitor); - - return visitor.m_allFiles; -} - -bool DependencyGraph::hasDependency(const QString &referenceFile, DependencyRole role) const -{ - QPair<bool, NodeRefSetIt> v = findVertex(referenceFile); - if (!v.first) - return false; - - NodeListIt nodeIt = v.second.value(); - - if (role == FilesDirectlyIncludedBy || role == FilesIncludedBy) - return nodeIt->m_out != 0; - - return nodeIt->m_in != 0; -} - -void DependencyGraph::discard() -{ - cancel(); - - for (NodeListIt it = m_nodes.begin(); it != m_nodes.end(); ++it) { - deleteAdjacencies(it->m_out); - deleteAdjacencies(it->m_in); - } - m_nodes.clear(); - m_nodesRefs.clear(); - m_files.clear(); -} - - -DependencyGraph::Node::Node(const QString &fileName) - : m_fileName(fileName) - , m_out(0) - , m_in(0) -{} - -DependencyGraph::AdjacencyNode::AdjacencyNode(NodeListIt it) - : m_next(0) - , m_nodeIt(it) -{} - -QPair<bool, DependencyGraph::NodeRefSetIt> DependencyGraph::findVertex(const QString &s) const -{ - bool found = false; - NodeRefSetIt it = const_cast<NodeRefSet &>(m_nodesRefs).find(s); - if (it != m_nodesRefs.end()) - found = true; - return qMakePair(found, it); -} - -DependencyGraph::NodeRefSetIt DependencyGraph::insertVertex(const QString &s) -{ - Q_ASSERT(m_nodesRefs.find(s) == m_nodesRefs.end()); - - m_nodes.append(Node(s)); - return m_nodesRefs.insert(s, m_nodes.end() - 1); -} - -void DependencyGraph::insertEdge(DependencyGraph::NodeRefSetIt fromIt, - DependencyGraph::NodeRefSetIt toIt) -{ - NodeListIt nodeFromIt = fromIt.value(); - NodeListIt nodeToIt = toIt.value(); - - createAdjacency(&nodeFromIt->m_out, new AdjacencyNode(nodeToIt)); - createAdjacency(&nodeToIt->m_in, new AdjacencyNode(nodeFromIt)); -} - -void DependencyGraph::deleteAdjacencies(AdjacencyNode *node) -{ - while (node) { - AdjacencyNode *next = node->m_next; - delete node; - node = next; - } -} - -void DependencyGraph::createAdjacency(AdjacencyNode **node, AdjacencyNode *newNode) -{ - if (*node) - newNode->m_next = *node; - *node = newNode; -} diff --git a/src/plugins/clangcodemodel/dependencygraph.h b/src/plugins/clangcodemodel/dependencygraph.h deleted file mode 100644 index 26bd75538a..0000000000 --- a/src/plugins/clangcodemodel/dependencygraph.h +++ /dev/null @@ -1,236 +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 DEPENDENCYGRAPH_H -#define DEPENDENCYGRAPH_H - -#include "includetracker.h" - -#include <QtCore/QObject> -#include <QtCore/QStringList> -#include <QtCore/QLinkedList> -#include <QtCore/QHash> -#include <QtCore/QPair> -#include <QtCore/QQueue> -#include <QtCore/QFuture> -#include <QtCore/QFutureWatcher> -#include <QtCore/QDebug> - -namespace ClangCodeModel { -namespace Internal { - -class DependencyGraph : public QObject -{ - Q_OBJECT - Q_DISABLE_COPY(DependencyGraph) - -public: - DependencyGraph(); - ~DependencyGraph(); - - void addFile(const QString &fileName, const QStringList &compilationOptions); - - QFuture<void> compute(); - - enum DependencyRole - { - FilesDirectlyIncludedBy, // Only direct inclusions - FilesIncludedBy, // Both direct and indirect inclusions - FilesWhichDirectlyInclude, // This one is directly included from... - FilesWhichInclude // This one is directly or indirectly included from... - }; - - /* - * You should use this version if you simply want all the dependencies, no matter what. - */ - QStringList collectDependencies(const QString &referenceFile, DependencyRole role) const; - - /* - * You should use this version if you might be interested on a particular dependency - * and don't want to continue the search once you have found it. In this case you need - * supply a visitor. Currently the visitor concept simply requires that a type Visitor_T - * models a function that will receive a file string s and indicate whether or not to - * continue: - * - * Visitor_T().acceptFile(s) must be a valid expression. - * - */ - template <class Visitor_T> - void collectDependencies(const QString &referenceFile, - DependencyRole role, - Visitor_T *visitor) const; - - bool hasDependency(const QString &referenceFile, DependencyRole role) const; - - void discard(); - -signals: - void dependencyGraphAvailable(); - -private: - QList<QPair<QString, QStringList> > m_files; - IncludeTracker m_includeTracker; - QFutureWatcher<void> m_computeWatcher; - - void cancel(); - void computeCore(); - - // The dependency graph is represent as an adjacency list. The vertices contains - // a list of *out* edges and a list of *in* edges. Each vertex corresponds to a file. - // Its out edges correspond to the files which get directly included by this one, while - // its in edges correspond to files that directly include this one. - // - // For better space efficiency, the adjacency nodes doen't explicitly store the file - // names themselves, but rather an iterator to the corresponding vertex. In addition, - // for speed efficiency we keep track of a hash table that contains iterators to the - // actual vertex storage container, which actually contains the strings for the file - // names. The vertex container itself is a linked list, it has the semantics we need, - // in particular regarding iterator invalidation. - - struct AdjacencyNode; - struct Node - { - Node(const QString &fileName); - - QString m_fileName; - AdjacencyNode *m_out; - AdjacencyNode *m_in; - }; - - typedef QLinkedList<Node> NodeList; - typedef NodeList::iterator NodeListIt; - typedef QHash<QString, NodeListIt> NodeRefSet; - typedef NodeRefSet::iterator NodeRefSetIt; - - struct AdjacencyNode - { - AdjacencyNode(NodeListIt it); - - AdjacencyNode *m_next; - NodeListIt m_nodeIt; - }; - - - void processIncludes(NodeRefSetIt currentFileIt, - const QStringList &compilationOptions); - - template <class Visitor_T> - void collectFilesBFS(NodeListIt nodeIt, DependencyRole role, Visitor_T *visitor) const; - - - // Core graph operations and data - - QPair<bool, NodeRefSetIt> findVertex(const QString &s) const; - NodeRefSetIt insertVertex(const QString &s); - void insertEdge(NodeRefSetIt fromIt, NodeRefSetIt toIt); - - void deleteAdjacencies(AdjacencyNode *node); - void createAdjacency(AdjacencyNode **node, AdjacencyNode *newNode); - - NodeList m_nodes; - NodeRefSet m_nodesRefs; -}; - -template <class Visitor_T> -void DependencyGraph::collectDependencies(const QString &referenceFile, - DependencyRole role, - Visitor_T *visitor) const -{ - if (m_computeWatcher.isRunning()) - return; - - QPair<bool, NodeRefSetIt> v = findVertex(referenceFile); - if (!v.first) - return; - - NodeListIt nodeIt = v.second.value(); - - if (role == FilesDirectlyIncludedBy || role == FilesWhichDirectlyInclude) { - AdjacencyNode *adj; - if (role == FilesDirectlyIncludedBy) - adj = nodeIt->m_out; - else - adj = nodeIt->m_in; - - for (; adj; adj = adj->m_next) { - NodeListIt dependentIt = adj->m_nodeIt; - if (visitor->acceptFile(dependentIt->m_fileName)) - return; - } - } else { - collectFilesBFS(nodeIt, role, visitor); - } -} - -template <class Visitor_T> -void DependencyGraph::collectFilesBFS(NodeListIt nodeIt, - DependencyRole role, - Visitor_T *visitor) const -{ - Q_ASSERT(role == FilesIncludedBy || role == FilesWhichInclude); - - if (m_computeWatcher.isRunning()) - return; - - QQueue<NodeListIt> q; - q.enqueue(nodeIt); - - QSet<QString> visited; - visited.insert(nodeIt->m_fileName); - - while (!q.isEmpty()) { - NodeListIt currentIt = q.dequeue(); - AdjacencyNode *adj; - if (role == FilesIncludedBy) - adj = currentIt->m_out; - else - adj = currentIt->m_in; - while (adj) { - NodeListIt adjNodeIt = adj->m_nodeIt; - adj = adj->m_next; - - const QString &adjFileName = adjNodeIt->m_fileName; - if (visited.contains(adjFileName)) - continue; - - if (visitor->acceptFile(adjFileName)) - return; - - visited.insert(adjFileName); - q.enqueue(adjNodeIt); - } - } -} - - -} // Internal -} // ClangCodeModel - -#endif // DEPENDENCYGRAPH_H diff --git a/src/plugins/clangcodemodel/diagnostic.cpp b/src/plugins/clangcodemodel/diagnostic.cpp deleted file mode 100644 index d9646ad180..0000000000 --- a/src/plugins/clangcodemodel/diagnostic.cpp +++ /dev/null @@ -1,64 +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 "diagnostic.h" - -#include <QtCore/QCoreApplication> -#include <QtCore/QStringList> - -using namespace ClangCodeModel; - -Diagnostic::Diagnostic() - : m_severity(Unknown) - , m_length(0) -{} - -Diagnostic::Diagnostic(Severity severity, const SourceLocation &location, unsigned length, const QString &spelling) - : m_severity(severity) - , m_loc(location) - , m_length(length) - , m_spelling(spelling) -{} - -const QString Diagnostic::severityAsString() const -{ - if (m_severity == Unknown) - return QString(); - - static QStringList strs = QStringList() - << QCoreApplication::translate("ClangCodeModel::Diagnostic", "ignored") - << QCoreApplication::translate("ClangCodeModel::Diagnostic", "note") - << QCoreApplication::translate("ClangCodeModel::Diagnostic", "warning") - << QCoreApplication::translate("ClangCodeModel::Diagnostic", "error") - << QCoreApplication::translate("ClangCodeModel::Diagnostic", "fatal") - ; - - return strs.at(m_severity); -} diff --git a/src/plugins/clangcodemodel/diagnostic.h b/src/plugins/clangcodemodel/diagnostic.h deleted file mode 100644 index d34f2ea36e..0000000000 --- a/src/plugins/clangcodemodel/diagnostic.h +++ /dev/null @@ -1,83 +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_DIAGNOSTIC_H -#define CLANG_DIAGNOSTIC_H - -#include "clang_global.h" -#include "sourcelocation.h" - -#include <QMetaType> - -namespace ClangCodeModel { - -class CLANG_EXPORT Diagnostic -{ -public: - enum Severity { - Unknown = -1, - Ignored = 0, - Note = 1, - Warning = 2, - Error = 3, - Fatal = 4 - }; - -public: - Diagnostic(); - Diagnostic(Severity severity, const SourceLocation &location, unsigned length, const QString &spelling); - - Severity severity() const - { return m_severity; } - - const QString severityAsString() const; - - const SourceLocation &location() const - { return m_loc; } - - unsigned length() const - { return m_length; } - - const QString &spelling() const - { return m_spelling; } - -private: - Severity m_severity; - SourceLocation m_loc; - unsigned m_length; - QString m_spelling; -}; - -} // namespace ClangCodeModel - -Q_DECLARE_METATYPE(ClangCodeModel::Diagnostic) -Q_DECLARE_METATYPE(QList<ClangCodeModel::Diagnostic>) - -#endif // CLANG_DIAGNOSTIC_H diff --git a/src/plugins/clangcodemodel/fastindexer.cpp b/src/plugins/clangcodemodel/fastindexer.cpp deleted file mode 100644 index 6bc669551c..0000000000 --- a/src/plugins/clangcodemodel/fastindexer.cpp +++ /dev/null @@ -1,37 +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 "fastindexer.h" - -using namespace ClangCodeModel::Internal; - -FastIndexer::~FastIndexer() -{ -} diff --git a/src/plugins/clangcodemodel/index.cpp b/src/plugins/clangcodemodel/index.cpp deleted file mode 100644 index f94cd165aa..0000000000 --- a/src/plugins/clangcodemodel/index.cpp +++ /dev/null @@ -1,491 +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 "index.h" - -#include <QStringList> -#include <QLinkedList> -#include <QHash> -#include <QDataStream> -#include <QPair> -#include <QFileInfo> -#include <QMutex> -#include <QMutexLocker> - -namespace ClangCodeModel { -namespace Internal { - -class ClangSymbolSearcher; - -class IndexPrivate -{ -public: - IndexPrivate(); - - void insertSymbol(const Symbol &symbol, const QDateTime &timeStamp); - QList<Symbol> symbols(const QString &fileName) const; - QList<Symbol> symbols(const QString &fileName, Symbol::Kind kind) const; - QList<Symbol> symbols(const QString &fileName, Symbol::Kind kind, const QString &uqName) const; - QList<Symbol> symbols(const QString &fileName, const QString &uqName) const; - QList<Symbol> symbols(Symbol::Kind kind) const; - - void match(ClangSymbolSearcher *searcher) const; - - void insertFile(const QString &fileName, const QDateTime &timeStamp); - void removeFile(const QString &fileName); - void removeFiles(const QStringList &fileNames); - bool containsFile(const QString &fileName) const; - QStringList files() const; - - void clear(); - - bool isEmpty() const; - - void trackTimeStamp(const Symbol &symbol, const QDateTime &timeStamp); - void trackTimeStamp(const QString &fileName, const QDateTime &timeStamp); - - bool validate(const QString &fileName) const; - - QByteArray serialize() const; - void deserialize(const QByteArray &data); - -private: - typedef QLinkedList<Symbol> SymbolCont; - typedef SymbolCont::iterator SymbolIt; - - typedef QHash<QString, QList<SymbolIt> > NameIndex; - typedef QHash<Symbol::Kind, NameIndex> KindIndex; - typedef QHash<QString, KindIndex> FileIndex; - - typedef QList<SymbolIt>::iterator SymbolIndexIt; - typedef NameIndex::iterator NameIndexIt; - typedef KindIndex::iterator KindIndexIt; - typedef FileIndex::iterator FileIndexIt; - typedef FileIndex::const_iterator FileIndexCIt; - - void insertSymbol(const Symbol &symbol); - void removeSymbol(SymbolIndexIt it); - - QPair<bool, SymbolIndexIt> findEquivalentSymbol(const Symbol &symbol); - void updateEquivalentSymbol(SymbolIndexIt it, const Symbol &symbol); - - void createIndexes(SymbolIt it); - QList<SymbolIt> removeIndexes(const QString &fileName); - - static QList<Symbol> symbolsFromIterators(const QList<SymbolIt> &symbolList); - - // @TODO: Sharing of compilation options... - - mutable QMutex m_mutex; - SymbolCont m_container; - FileIndex m_files; - QHash<QString, QDateTime> m_timeStamps; -}; - -} // namespace Internal -} // namespace ClangCodeModel - -using namespace ClangCodeModel; -using namespace Internal; - -IndexPrivate::IndexPrivate() - : m_mutex(QMutex::Recursive) -{ -} - -void IndexPrivate::createIndexes(SymbolIt it) -{ - m_files[it->m_location.fileName()][it->m_kind][it->m_name].append(it); -} - -QList<QLinkedList<Symbol>::iterator> IndexPrivate::removeIndexes(const QString &fileName) -{ - QList<SymbolIt> iterators; - KindIndex kindIndex = m_files.take(fileName); - KindIndexIt it = kindIndex.begin(); - KindIndexIt eit = kindIndex.end(); - for (; it != eit; ++it) { - NameIndex nameIndex = *it; - NameIndexIt nit = nameIndex.begin(); - NameIndexIt neit = nameIndex.end(); - for (; nit != neit; ++nit) - iterators.append(*nit); - } - return iterators; -} - -void IndexPrivate::insertSymbol(const Symbol &symbol) -{ - QMutexLocker locker(&m_mutex); - - SymbolIt it = m_container.insert(m_container.begin(), symbol); - createIndexes(it); -} - -void IndexPrivate::insertSymbol(const Symbol &symbol, const QDateTime &timeStamp) -{ - const QPair<bool, SymbolIndexIt> &find = findEquivalentSymbol(symbol); - if (find.first) - updateEquivalentSymbol(find.second, symbol); - else - insertSymbol(symbol); - - trackTimeStamp(symbol, timeStamp); -} - -QPair<bool, IndexPrivate::SymbolIndexIt> IndexPrivate::findEquivalentSymbol(const Symbol &symbol) -{ - // Despite the loop below finding a symbol should be efficient, since we already filter - // the file name, the kind, and the qualified name through the indexing mechanism. In many - // cases it will iterate only once. - QList<SymbolIt> &byName = m_files[symbol.m_location.fileName()][symbol.m_kind][symbol.m_name]; - for (SymbolIndexIt it = byName.begin(); it != byName.end(); ++it) { - const Symbol &candidateSymbol = *(*it); - // @TODO: Overloads, template specializations - if (candidateSymbol.m_qualification == symbol.m_qualification) - return qMakePair(true, it); - } - - return qMakePair(false, QList<SymbolIt>::iterator()); -} - -void IndexPrivate::updateEquivalentSymbol(SymbolIndexIt it, const Symbol &symbol) -{ - SymbolIt symbolIt = *it; - - Q_ASSERT(symbolIt->m_kind == symbol.m_kind); - Q_ASSERT(symbolIt->m_qualification == symbol.m_qualification); - Q_ASSERT(symbolIt->m_name == symbol.m_name); - Q_ASSERT(symbolIt->m_location.fileName() == symbol.m_location.fileName()); - - symbolIt->m_location = symbol.m_location; -} - -void IndexPrivate::removeSymbol(SymbolIndexIt it) -{ - SymbolIt symbolIt = *it; - - m_container.erase(symbolIt); - - KindIndex &kindIndex = m_files[symbolIt->m_location.fileName()]; - NameIndex &nameIndex = kindIndex[symbolIt->m_kind]; - QList<SymbolIt> &byName = nameIndex[symbolIt->m_name]; - byName.erase(it); - if (byName.isEmpty()) { - nameIndex.remove(symbolIt->m_name); - if (nameIndex.isEmpty()) { - kindIndex.remove(symbolIt->m_kind); - if (kindIndex.isEmpty()) - m_files.remove(symbolIt->m_location.fileName()); - } - } -} - -QList<Symbol> IndexPrivate::symbols(const QString &fileName) const -{ - QMutexLocker locker(&m_mutex); - - QList<Symbol> all; - const QList<NameIndex> &byKind = m_files.value(fileName).values(); - foreach (const NameIndex &nameIndex, byKind) { - const QList<QList<SymbolIt> > &byName = nameIndex.values(); - foreach (const QList<SymbolIt> &symbols, byName) - all.append(symbolsFromIterators(symbols)); - } - return all; -} - -QList<Symbol> IndexPrivate::symbols(const QString &fileName, Symbol::Kind kind) const -{ - QMutexLocker locker(&m_mutex); - - QList<Symbol> all; - const QList<QList<SymbolIt> > &byName = m_files.value(fileName).value(kind).values(); - foreach (const QList<SymbolIt> &symbols, byName) - all.append(symbolsFromIterators(symbols)); - return all; -} - -QList<Symbol> IndexPrivate::symbols(const QString &fileName, - Symbol::Kind kind, - const QString &uqName) const -{ - QMutexLocker locker(&m_mutex); - - return symbolsFromIterators(m_files.value(fileName).value(kind).value(uqName)); -} - -QList<Symbol> IndexPrivate::symbols(Symbol::Kind kind) const -{ - QMutexLocker locker(&m_mutex); - - QList<Symbol> all; - FileIndexCIt it = m_files.begin(); - FileIndexCIt eit = m_files.end(); - for (; it != eit; ++it) - all.append(symbols(it.key(), kind)); - return all; -} - -void IndexPrivate::match(ClangSymbolSearcher *searcher) const -{ - QMutexLocker locker(&m_mutex); - Q_UNUSED(searcher); -// searcher->search(m_container); -} - -QList<Symbol> IndexPrivate::symbolsFromIterators(const QList<SymbolIt> &symbolList) -{ - QList<Symbol> all; - foreach (SymbolIt symbolIt, symbolList) - all.append(*symbolIt); - return all; -} - -void IndexPrivate::trackTimeStamp(const Symbol &symbol, const QDateTime &timeStamp) -{ - QMutexLocker locker(&m_mutex); - - trackTimeStamp(symbol.m_location.fileName(), timeStamp); -} - -void IndexPrivate::trackTimeStamp(const QString &fileName, const QDateTime &timeStamp) -{ - QMutexLocker locker(&m_mutex); - - // We keep track of time stamps on a per file basis (most recent one). - m_timeStamps[fileName] = timeStamp; -} - -bool IndexPrivate::validate(const QString &fileName) const -{ - QMutexLocker locker(&m_mutex); - - const QDateTime &timeStamp = m_timeStamps.value(fileName); - if (!timeStamp.isValid()) - return false; - - QFileInfo fileInfo(fileName); - if (fileInfo.lastModified() > timeStamp) - return false; - - return true; -} - -void IndexPrivate::insertFile(const QString &fileName, const QDateTime &timeStamp) -{ - QMutexLocker locker(&m_mutex); - - trackTimeStamp(fileName, timeStamp); -} - -QStringList IndexPrivate::files() const -{ - QMutexLocker locker(&m_mutex); - - return m_timeStamps.keys(); -} - -bool IndexPrivate::containsFile(const QString &fileName) const -{ - QMutexLocker locker(&m_mutex); - - return m_timeStamps.contains(fileName); -} - -void IndexPrivate::removeFile(const QString &fileName) -{ - QMutexLocker locker(&m_mutex); - - const QList<SymbolIt> &iterators = removeIndexes(fileName); - foreach (SymbolIt it, iterators) - m_container.erase(it); - - m_timeStamps.remove(fileName); -} - -void IndexPrivate::removeFiles(const QStringList &fileNames) -{ - QMutexLocker locker(&m_mutex); - - foreach (const QString &fileName, fileNames) - removeFile(fileName); -} - -void IndexPrivate::clear() -{ - QMutexLocker locker(&m_mutex); - - m_container.clear(); - m_files.clear(); - m_timeStamps.clear(); -} - -bool IndexPrivate::isEmpty() const -{ - QMutexLocker locker(&m_mutex); - - return m_timeStamps.isEmpty(); -} - -QByteArray IndexPrivate::serialize() const -{ - QMutexLocker locker(&m_mutex); - - QByteArray data; - QDataStream stream(&data, QIODevice::WriteOnly); - - stream << (quint32)0x0A0BFFEE; - stream << (quint16)1; - stream.setVersion(QDataStream::Qt_4_7); - stream << m_container; - stream << m_timeStamps; - - return data; -} - -void IndexPrivate::deserialize(const QByteArray &data) -{ - QMutexLocker locker(&m_mutex); - - clear(); - - // @TODO: Version compatibility handling. - - QDataStream stream(data); - - quint32 header; - stream >> header; - if (header != 0x0A0BFFEE) - return; - - quint16 indexVersion; - stream >> indexVersion; - if (indexVersion != 1) - return; - - stream.setVersion(QDataStream::Qt_4_7); - - SymbolCont symbols; - stream >> symbols; - stream >> m_timeStamps; - - // @TODO: Overload the related functions with batch versions. - foreach (const Symbol &symbol, symbols) - insertSymbol(symbol); -} - - -Index::Index() - : d(new IndexPrivate) -{} - -Index::~Index() -{} - -void Index::insertSymbol(const Symbol &symbol, const QDateTime &timeStamp) -{ - d->insertSymbol(symbol, timeStamp); -} - -QList<Symbol> Index::symbols(const QString &fileName) const -{ - return d->symbols(fileName); -} - -QList<Symbol> Index::symbols(const QString &fileName, Symbol::Kind kind) const -{ - return d->symbols(fileName, kind); -} - -QList<Symbol> Index::symbols(const QString &fileName, Symbol::Kind kind, const QString &uqName) const -{ - return d->symbols(fileName, kind, uqName); -} - -QList<Symbol> Index::symbols(Symbol::Kind kind) const -{ - return d->symbols(kind); -} - -void Index::match(ClangSymbolSearcher *searcher) const -{ - d->match(searcher); -} - -void Index::insertFile(const QString &fileName, const QDateTime &timeStamp) -{ - d->insertFile(fileName, timeStamp); -} - -QStringList Index::files() const -{ - return d->files(); -} - -bool Index::containsFile(const QString &fileName) const -{ - return d->containsFile(fileName); -} - -void Index::removeFile(const QString &fileName) -{ - d->removeFile(fileName); -} - -void Index::removeFiles(const QStringList &fileNames) -{ - d->removeFiles(fileNames); -} - -void Index::clear() -{ - d->clear(); -} - -bool Index::isEmpty() const -{ - return d->isEmpty(); -} - -bool Index::validate(const QString &fileName) const -{ - return d->validate(fileName); -} - -QByteArray Index::serialize() const -{ - return d->serialize(); -} - -void Index::deserialize(const QByteArray &data) -{ - d->deserialize(data); -} diff --git a/src/plugins/clangcodemodel/index.h b/src/plugins/clangcodemodel/index.h deleted file mode 100644 index 6809e4676a..0000000000 --- a/src/plugins/clangcodemodel/index.h +++ /dev/null @@ -1,88 +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 INDEX_H -#define INDEX_H - -#include "symbol.h" - -#include <QtCore/QByteArray> -#include <QtCore/QString> -#include <QtCore/QList> -#include <QtCore/QScopedPointer> -#include <QtCore/QDateTime> -#include <QStringList> - -namespace ClangCodeModel { - -class Symbol; - -namespace Internal { - -class ClangSymbolSearcher; -class IndexPrivate; - -class Index -{ -public: - Index(); - ~Index(); - - void insertSymbol(const Symbol &symbol, const QDateTime &timeStamp); - QList<Symbol> symbols(const QString &fileName) const; - QList<Symbol> symbols(const QString &fileName, Symbol::Kind kind) const; - QList<Symbol> symbols(const QString &fileName, Symbol::Kind kind, const QString &uqName) const; - QList<Symbol> symbols(Symbol::Kind kind) const; - - void match(ClangSymbolSearcher *searcher) const; - - void insertFile(const QString &fileName, const QDateTime &timeStamp); - void removeFile(const QString &fileName); - void removeFiles(const QStringList &fileNames); - bool containsFile(const QString &fileName) const; - QStringList files() const; - - bool validate(const QString &fileName) const; - - void clear(); - - bool isEmpty() const; - - QByteArray serialize() const; - void deserialize(const QByteArray &data); - -private: - QScopedPointer<IndexPrivate> d; -}; - -} // Internal -} // ClangCodeModel - -#endif // INDEX_H diff --git a/src/plugins/clangcodemodel/indexer.cpp b/src/plugins/clangcodemodel/indexer.cpp deleted file mode 100644 index f44c51d4c1..0000000000 --- a/src/plugins/clangcodemodel/indexer.cpp +++ /dev/null @@ -1,1284 +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 "clangutils.h" -#include "indexer.h" -#include "index.h" -#include "cxraii.h" -#include "sourcelocation.h" -#include "utils_p.h" -#include "pchmanager.h" -#include "raii/scopedclangoptions.h" - -#include <clang-c/Index.h> - -#include <coreplugin/editormanager/editormanager.h> -#include <coreplugin/icore.h> -#include <coreplugin/progressmanager/progressmanager.h> -#include <utils/fileutils.h> -#include <utils/QtConcurrentTools> - -#include <QDebug> -#include <QVector> -#include <QHash> -#include <QSet> -#include <QFile> -#include <QFileInfo> -#include <QFutureWatcher> -#include <QDir> -#include <QFuture> -#include <QTime> -#include <QRunnable> -#include <QThreadPool> -#include <QDateTime> -#include <QStringBuilder> - -using namespace Utils; -using namespace ClangCodeModel; -using namespace Internal; - -namespace ClangCodeModel { - -// The indexing result, containing the symbols found, reported by the indexer processor. -struct IndexingResult -{ - typedef CppTools::ProjectPart ProjectPart; - - IndexingResult() - : m_unit(Unit::create()) - {} - - IndexingResult(const QVector<Symbol> &symbol, - const QSet<QString> &processedFiles, - const Unit::Ptr &unit, - const ProjectPart::Ptr &projectPart) - : m_symbolsInfo(symbol) - , m_processedFiles(processedFiles) - , m_unit(unit) - , m_projectPart(projectPart) - {} - - QVector<Symbol> m_symbolsInfo; - QSet<QString> m_processedFiles; - Unit::Ptr m_unit; - ProjectPart::Ptr m_projectPart; -}; - -class LibClangIndexer; - -class IndexerPrivate : public QObject -{ - Q_OBJECT - -public: - typedef CppTools::ProjectPart ProjectPart; - -public: - IndexerPrivate(Indexer *indexer); - ~IndexerPrivate() - { cancel(true); } - - // This enumeration is used to index a vector. So be careful when changing. - enum FileType { - ImplementationFile = 0, - HeaderFile, - TotalFileTypes - }; - - struct FileData - { - FileData() : m_upToDate(false) {} - FileData(const QString &fileName, - const ProjectPart::Ptr &projectPart, - bool upToDate = false) - : m_fileName(fileName) - , m_projectPart(projectPart) - , m_upToDate(upToDate) - , m_managementOptions(CXTranslationUnit_DetailedPreprocessingRecord - | CXTranslationUnit_Incomplete) - {} - - QString m_fileName; - ProjectPart::Ptr m_projectPart; - bool m_upToDate; - unsigned m_managementOptions; - }; - - void synchronize(const QVector<IndexingResult> &results); - void finished(LibClangIndexer *indexer); - bool noIndexersRunning() const; - -private: - mutable QMutex m_mutex; - - void indexingFinished(); - void cancelIndexing(); - int runningIndexerCount() const; - -public slots: - void dependencyGraphComputed(); - void restoredSymbolsAnalysed(); - -public: - enum IndexingMode { - RelaxedIndexing, // Index symbols from any file. - ConstrainedIndexing // Index symbols only from the requested files. - }; - - void startLoading(); - void concludeLoading(); - - void computeDependencyGraph(); - void analyzeRestoredSymbols(); - - void runQuickIndexing(const Unit::Ptr &unit, const ProjectPart::Ptr &part); - void run(); - void run(const QStringList &fileNames); - void runCore(const QHash<QString, FileData> &headers, - const QHash<QString, FileData> &impls, - IndexingMode mode); - void watchIndexingThreads(QFutureInterface<void> &future); - bool isBusy() const; - void cancel(bool wait); - void reset(); - - bool addFile(const QString &fileName, - ProjectPart::Ptr projectPart); - void addOrUpdateFileData(const QString &fileName, - ProjectPart::Ptr projectPart, - bool upToDate); - QStringList allFiles() const; - bool isTrackingFile(const QString &fileName, FileType type) const; - static FileType identifyFileType(const QString &fileName); - static void populateFileNames(QStringList *all, const QList<FileData> &data); - QStringList compilationOptions(const QString &fileName) const; - - bool deserealizeSymbols(); - void serializeSymbols() const; - - QList<Symbol> symbols(Symbol::Kind kind) const; - QList<Symbol> symbols(const QString &fileName, const Symbol::Kind kind) const; - void match(ClangSymbolSearcher *searcher) const; - - Indexer *m_q; - QVector<QHash<QString, FileData> > m_files; - Index m_index; - bool m_hasQueuedFullRun; - QSet<QString> m_queuedFilesRun; - QString m_storagePath; - bool m_isLoaded; -// DependencyGraph m_dependencyGraph; - QScopedPointer<QFutureWatcher<void> >m_loadingWatcher; - QScopedPointer<QFutureWatcher<void> >m_indexingWatcher; - QThreadPool m_indexingPool; - QSet<LibClangIndexer *> m_runningIndexers; -}; - -} // ClangCodeModel - -Q_DECLARE_METATYPE(IndexingResult) - -namespace { - -struct ScopepTimer -{ - ScopepTimer(int id = 0) : m_id(id) { m_t.start(); } - ~ScopepTimer() { qDebug() << "\t#Timer" << m_id << ":" << m_t.elapsed() << "ms"; } - int m_id; - QTime m_t; -}; - -} // Anonymous - -namespace ClangCodeModel { - -class LibClangIndexer: public QRunnable -{ -protected: - typedef CppTools::ProjectPart ProjectPart; - -public: - LibClangIndexer(IndexerPrivate *indexer) - : m_indexer(indexer) - , m_isCanceled(false) - {} - - virtual ~LibClangIndexer() - {} - - void cancel() - { m_isCanceled = true; } - -protected: - void propagateResults(const ProjectPart::Ptr &projectPart) - { - if (!isCanceled()) { - QVector<IndexingResult> indexingResults; - indexingResults.reserve(m_allFiles.size()); - - foreach (const QString &fn, m_allFiles.keys()) { - QVector<Symbol> symbols; unfoldSymbols(symbols, fn); - QSet<QString> processedFiles = QSet<QString>::fromList(m_allFiles.keys()); - Unit::Ptr unit = Unit::create(fn); - IndexingResult indexingResult(symbols, processedFiles, unit, projectPart); - indexingResults.append(indexingResult); - - // TODO: includes need to be propagated to the dependency table. - } - m_indexer->synchronize(indexingResults); - } - - qDeleteAll(m_allFiles.values()); - m_allFiles.clear(); - qDeleteAll(m_allSymbols); - m_allSymbols.clear(); - } - -protected: - static inline LibClangIndexer *indexer(CXClientData d) - { return static_cast<LibClangIndexer *>(d); } - - static int abortQuery(CXClientData client_data, void *reserved) { - Q_UNUSED(reserved); - - return indexer(client_data)->isCanceled(); - } - - static void diagnostic(CXClientData client_data, CXDiagnosticSet diagSet, void *reserved) { - Q_UNUSED(client_data); - Q_UNUSED(diagSet); - Q_UNUSED(reserved); - } - - static CXIdxClientFile enteredMainFile(CXClientData client_data, CXFile file, void *reserved) { - Q_UNUSED(client_data); - Q_UNUSED(reserved); - - const QString fileName = getQString(clang_getFileName(file)); -// qDebug() << "enteredMainFile:" << fileName; - LibClangIndexer *lci = indexer(client_data); - File *f = lci->file(fileName); - f->setMainFile(); - - return f; - } - - static CXIdxClientFile includedFile(CXClientData client_data, const CXIdxIncludedFileInfo *info) { - Q_UNUSED(client_data); - - File *includingFile = 0; - clang_indexLoc_getFileLocation(info->hashLoc, reinterpret_cast<CXIdxClientFile*>(&includingFile), 0, 0, 0, 0); - - const QString fileName = getQString(clang_getFileName(info->file)); - File *f = indexer(client_data)->file(fileName); - - if (includingFile) - includingFile->addInclude(f); - - return f; - } - - static CXIdxClientFile importedASTFile(CXClientData client_data, const CXIdxImportedASTFileInfo *info) { - const QString fileName = getQString(clang_getFileName(info->file)); - -// qDebug() << "importedASTFile:" << fileName; - - indexer(client_data)->m_importedASTs.insert(fileName, false); - - return info->file; - } - - static CXIdxClientContainer startedTranslationUnit(CXClientData client_data, void *reserved) { - Q_UNUSED(client_data); - Q_UNUSED(reserved); - -// qDebug() << "startedTranslationUnit"; - return 0; - } - - static void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo *info) { - LibClangIndexer *lci = indexer(client_data); - - File *includingFile = 0; - unsigned line = 0, column = 0, offset = 0; - clang_indexLoc_getFileLocation(info->loc, reinterpret_cast<CXIdxClientFile*>(&includingFile), 0, &line, &column, &offset); - - QString kind = getQString(clang_getCursorKindSpelling(info->cursor.kind)); - QString displayName = getQString(clang_getCursorDisplayName(info->cursor)); - QString spellingName = getQString(clang_getCursorSpelling(info->cursor)); -// qDebug() << (includingFile ? includingFile->name() : QLatin1String("<UNKNOWN FILE>")) << ":"<<line<<":"<<column<<": display name ="<<displayName<<"spelling name ="<<spellingName<<"of kind"<<kind; - - Symbol *sym = lci->newSymbol(info->cursor.kind, displayName, spellingName, includingFile, line, column, offset); - - // TODO: add to decl container... - if (includingFile) // TODO: check why includingFile can be null... - includingFile->addSymbol(sym); - - if (const CXIdxContainerInfo *semanticContainer = info->semanticContainer) { - if (Symbol *container = static_cast<Symbol *>(clang_index_getClientContainer(semanticContainer))) { - sym->semanticContainer = container; - container->addSymbol(sym); - } - } - - // TODO: ObjC containers - // TODO: index forward decls too? - - if (info->declAsContainer) - clang_index_setClientContainer(info->declAsContainer, sym); - } - - static void indexEntityReference(CXClientData client_data, const CXIdxEntityRefInfo *info) { - Q_UNUSED(client_data); - Q_UNUSED(info); - - // TODO: well, we do get the info, so why not (optionally?) remember all references? - } - -protected: - struct File; - struct Symbol; - - typedef QHash<QString, File *> FilesByName; - struct File - { - File(const QString &fileName) - : m_fileName(fileName) - {} - - void addInclude(File *f) - { -// assert(f); - m_includes.insert(f->name(), f); - } - - QList<File *> includes() const - { return m_includes.values(); } - - QString name() const - { return m_fileName; } - - void setMainFile(bool isMainFile = true) - { m_isMainFile = isMainFile; } - - bool isMainFile() const - { return m_isMainFile; } - - void addSymbol(Symbol *symbol) - { -// assert(symbol); - m_symbols.append(symbol); - } - - QVector<Symbol *> symbols() const - { return m_symbols; } - - private: - QString m_fileName; - FilesByName m_includes; - bool m_isMainFile; - QVector<Symbol *> m_symbols; - }; - - struct Symbol - { - Symbol(enum CXCursorKind kind, const QString &displayName, const QString &spellingName, File *file, unsigned line, unsigned column, unsigned offset) - : kind(kind) - , displayName(displayName) - , spellingName(spellingName) - , file(file) - , line(line) - , column(column) - , offset(offset) - , semanticContainer(0) - {} - - QString spellKind() const - { return getQString(clang_getCursorKindSpelling(kind)); } - - void addSymbol(Symbol *symbol) - { symbols.append(symbol); } - - enum CXCursorKind kind; - QString displayName, spellingName; - File *file; - unsigned line, column, offset; - Symbol *semanticContainer; - QVector<Symbol *> symbols; - }; - -protected: - bool isCanceled() const - { return m_isCanceled; } - - void finish() - { m_indexer->finished(this); } - - File *file(const QString &fileName) - { - File *f = m_allFiles[fileName]; - if (!f) { - f = new File(fileName); - m_allFiles.insert(fileName, f); - } - return f; - } - - Symbol *newSymbol(enum CXCursorKind kind, const QString &displayName, const QString &spellingName, File *file, unsigned line, unsigned column, unsigned offset) - { - Symbol *s = new Symbol(kind, displayName, spellingName, file, line, column, offset); - m_allSymbols.append(s); - return s; - } - - void dumpInfo() - { - qDebug() << "=== indexing info dump ==="; - qDebug() << "indexed" << m_allFiles.size() << "files. Main files:"; - foreach (const File *f, m_allFiles) { - if (!f->isMainFile()) - continue; - qDebug() << f->name() << ":"; - foreach (const File *inc, f->includes()) - qDebug() << " includes" << inc->name(); - dumpSymbols(f->symbols(), QByteArray(" ")); - } - - qDebug() << "=== end of dump ==="; - } - - void dumpSymbols(const QVector<Symbol *> &symbols, const QByteArray &indent) - { - if (symbols.isEmpty()) - return; - - qDebug("%scontained symbols:", indent.constData()); - QByteArray newIndent = indent + " "; - foreach (const Symbol *s, symbols) { - qDebug("%s%s (%s)", newIndent.constData(), s->spellingName.toUtf8().constData(), s->spellKind().toUtf8().constData()); - dumpSymbols(s->symbols, newIndent); - } - } - - void unfoldSymbols(QVector<Symbol> &result, const QString &fileName) { - const QVector<Symbol *> symbolsForFile = file(fileName)->symbols(); - foreach (const Symbol *s, symbolsForFile) { - unfoldSymbols(s, result); - } - } - - void unfoldSymbols(const Symbol *s, QVector<Symbol> &result) { - if (!s->file) - return; - - Symbol sym; - sym.m_name = s->spellingName; - sym.m_qualification = s->spellingName; - - static QLatin1String sep("::"); - for (Symbol *parent = s->semanticContainer; parent; parent = parent->semanticContainer) - sym.m_qualification = parent->spellingName + sep + sym.m_qualification; - - sym.m_location = SourceLocation(s->file->name(), s->line, s->column, s->offset); - - switch (s->kind) { - case CXCursor_EnumDecl: sym.m_kind = Symbol::Enum; break; - case CXCursor_StructDecl: - case CXCursor_ClassDecl: sym.m_kind = Symbol::Class; break; - case CXCursor_CXXMethod: sym.m_kind = Symbol::Method; break; - case CXCursor_FunctionTemplate: - case CXCursor_FunctionDecl: sym.m_kind = Symbol::Function; break; - case CXCursor_DeclStmt: sym.m_kind = Symbol::Declaration; break; - case CXCursor_Constructor: sym.m_kind = Symbol::Constructor; break; - case CXCursor_Destructor: sym.m_kind = Symbol::Destructor; break; - default: sym.m_kind = Symbol::Unknown; break; - } - - result.append(sym); - } - -protected: - static IndexerCallbacks IndexCB; - -protected: - IndexerPrivate *m_indexer; - bool m_isCanceled; - QHash<QString, bool> m_importedASTs; - FilesByName m_allFiles; - QVector<Symbol *> m_allSymbols; -}; - -IndexerCallbacks LibClangIndexer::IndexCB = { - abortQuery, - diagnostic, - enteredMainFile, - includedFile, - importedASTFile, - startedTranslationUnit, - indexDeclaration, - indexEntityReference -}; - -class ProjectPartIndexer: public LibClangIndexer -{ -public: - ProjectPartIndexer(IndexerPrivate *indexer, const QList<IndexerPrivate::FileData> &todo) - : LibClangIndexer(indexer) - , m_todo(todo) - {} - - void run() - { - if (isCanceled() || m_todo.isEmpty()) { - finish(); - return; - } - - const ProjectPart::Ptr &pPart = m_todo[0].m_projectPart; - -restart: - CXIndex idx; - if (!(idx = clang_createIndex(/* excludeDeclsFromPCH */ 1, - /* displayDiagnosics=*/1))) { - qDebug() << "Could not create Index"; - return; - } - - CXIndexAction idxAction = clang_IndexAction_create(idx); - const unsigned index_opts = CXIndexOpt_SuppressWarnings; - - PchManager *pchManager = PchManager::instance(); - PchInfo::Ptr pchInfo = pchManager->pchInfo(pPart); - - for (int i = 0, ei = m_todo.size(); i < ei; ++i) { - const IndexerPrivate::FileData &fd = m_todo.at(i); - if (fd.m_upToDate) - continue; - - if (pchManager->pchInfo(pPart) != pchInfo) { - clang_IndexAction_dispose(idxAction); - clang_disposeIndex(idx); - goto restart; - } - - QStringList opts = Utils::createClangOptions(pPart, fd.m_fileName); - if (!pchInfo.isNull()) - opts.append(Utils::createPCHInclusionOptions(pchInfo->fileName())); - - ScopedClangOptions scopedOpts(opts); - QByteArray fileName = fd.m_fileName.toUtf8(); - -// qDebug() << "Indexing file" << fd.m_fileName << "with options" << opts; - unsigned parsingOptions = fd.m_managementOptions; - parsingOptions |= CXTranslationUnit_SkipFunctionBodies; - - /*int result =*/ clang_indexSourceFile(idxAction, this, - &IndexCB, sizeof(IndexCB), - index_opts, fileName.constData(), - scopedOpts.data(), scopedOpts.size(), 0, 0, 0, - parsingOptions); - - // index imported ASTs: - foreach (const QString &astFile, m_importedASTs.keys()) { - if (m_importedASTs.value(astFile)) - continue; - - if (CXTranslationUnit TU = clang_createTranslationUnit( - idx, astFile.toUtf8().constData())) { - /*result =*/ clang_indexTranslationUnit(idxAction, this, - &IndexCB, - sizeof(IndexCB), - index_opts, TU); - clang_disposeTranslationUnit(TU); - } - - m_importedASTs[astFile] = true; - } - - propagateResults(fd.m_projectPart); - if (isCanceled()) - break; - } - -// dumpInfo(); - - clang_IndexAction_dispose(idxAction); - clang_disposeIndex(idx); - - finish(); - } - -private: - QList<IndexerPrivate::FileData> m_todo; -}; - -class QuickIndexer: public LibClangIndexer -{ -public: - QuickIndexer(IndexerPrivate *indexer, const Unit::Ptr &unit, const ProjectPart::Ptr&projectPart) - : LibClangIndexer(indexer) - , m_unit(unit) - , m_projectPart(projectPart) - {} - - void run() - { - if (isCanceled() || !m_unit->isLoaded()) { - finish(); - return; - } - - CXIndexAction idxAction = clang_IndexAction_create(m_unit->clangIndex()); - const unsigned index_opts = CXIndexOpt_SuppressWarnings; - -// qDebug() << "Indexing TU" << m_unit.fileName() << "..."; - /*int result =*/ clang_indexTranslationUnit(idxAction, this, - &IndexCB, sizeof(IndexCB), - index_opts, - m_unit->clangTranslationUnit()); - - propagateResults(m_projectPart); - - clang_IndexAction_dispose(idxAction); - finish(); - } - -private: - Unit::Ptr m_unit; - ProjectPart::Ptr m_projectPart; -}; - -} // ClangCodeModel - -IndexerPrivate::IndexerPrivate(Indexer *indexer) - : m_mutex(QMutex::Recursive) - , m_q(indexer) - , m_files(TotalFileTypes) - , m_hasQueuedFullRun(false) - , m_isLoaded(false) - , m_loadingWatcher(new QFutureWatcher<void>) - , m_indexingWatcher(new QFutureWatcher<void>) -{ -// const int magicThreadCount = QThread::idealThreadCount() * 4 / 3; - const int magicThreadCount = QThread::idealThreadCount() - 1; - m_indexingPool.setMaxThreadCount(std::max(magicThreadCount, 1)); - m_indexingPool.setExpiryTimeout(1000); -} - -void IndexerPrivate::runCore(const QHash<QString, FileData> & /*headers*/, - const QHash<QString, FileData> &impls, - IndexingMode /*mode*/) -{ - QMutexLocker locker(&m_mutex); - - typedef QHash<QString, FileData>::const_iterator FileContIt; - QHash<ProjectPart::Ptr, QList<IndexerPrivate::FileData> > parts; - typedef QHash<ProjectPart::Ptr, QList<IndexerPrivate::FileData> >::Iterator PartIter; - - QList<Core::IDocument *> docs = Core::DocumentModel::openedDocuments(); - QSet<QString> openDocs; - foreach (Core::IDocument *doc, docs) - openDocs.insert(doc->filePath().toString()); - - for (FileContIt tit = impls.begin(), eit = impls.end(); tit != eit; ++tit) { - if (!tit->m_upToDate && openDocs.contains(tit.key())) { - const IndexerPrivate::FileData &fd = tit.value(); - parts[fd.m_projectPart].append(fd); - } - } - - if (parts.isEmpty()) - return; - - for (PartIter i = parts.begin(), ei = parts.end(); i != ei; ++i) { - ProjectPartIndexer *ppi = new ProjectPartIndexer(this, i.value()); - m_runningIndexers.insert(ppi); - m_indexingPool.start(ppi); - } - - QFuture<void> task = QtConcurrent::run(&IndexerPrivate::watchIndexingThreads, this); - m_indexingWatcher->setFuture(task); - emit m_q->indexingStarted(task); -} - -void IndexerPrivate::watchIndexingThreads(QFutureInterface<void> &future) -{ - int maxTodo = runningIndexerCount(); - future.setProgressRange(0, maxTodo); - - int todo = -1; - while (todo) { - int newTodo = runningIndexerCount(); - if (todo != newTodo) - future.setProgressValue(maxTodo - newTodo); - todo = newTodo; - if (future.isCanceled()) { - cancelIndexing(); - return; - } - m_indexingPool.waitForDone(500); - } -} - -void IndexerPrivate::run() -{ - Q_ASSERT(m_isLoaded); - - QMutexLocker locker(&m_mutex); - - if (m_runningIndexers.isEmpty()) { - runCore(m_files.value(HeaderFile), - m_files.value(ImplementationFile), - RelaxedIndexing); - } else { - m_hasQueuedFullRun = true; - cancelIndexing(); - } -} - -void IndexerPrivate::run(const QStringList &fileNames) -{ - Q_ASSERT(m_isLoaded); - QMutexLocker locker(&m_mutex); - - if (noIndexersRunning()) { - QVector<QHash<QString, FileData> > files(TotalFileTypes); - foreach (const QString &fileName, fileNames) { - FileType type = identifyFileType(fileName); - if (!isTrackingFile(fileName, type)) { - // @TODO - continue; - } - - FileData *data = &m_files[type][fileName]; - data->m_upToDate = false; - files[type].insert(fileName, *data); - m_index.removeFile(fileName); - } - runCore(files.value(HeaderFile), - files.value(ImplementationFile), - ConstrainedIndexing); - } else { - m_queuedFilesRun.unite(fileNames.toSet()); - } -} - -bool IndexerPrivate::isBusy() const -{ - return !noIndexersRunning() || m_loadingWatcher->isRunning(); -} - -void IndexerPrivate::cancel(bool wait) -{ -// m_dependencyGraph.discard(); - - m_loadingWatcher->cancel(); - cancelIndexing(); - if (wait) { - m_loadingWatcher->waitForFinished(); - m_indexingWatcher->waitForFinished(); - while (!noIndexersRunning()) - m_indexingPool.waitForDone(100); - } -} - -void IndexerPrivate::reset() -{ - cancel(true); - serializeSymbols(); - - for (int i = 0; i < TotalFileTypes; ++i) - m_files[i].clear(); - m_hasQueuedFullRun = false; - m_queuedFilesRun.clear(); - m_storagePath.clear(); - m_index.clear(); - m_isLoaded = false; -} - -void IndexerPrivate::synchronize(const QVector<IndexingResult> &results) -{ - Q_UNUSED(results); -#if 0 - foreach (const IndexingResult &result, results) { - QMutexLocker locker(&m_mutex); - - foreach (const Symbol &symbol, result.m_symbolsInfo) { - addOrUpdateFileData(symbol.m_location.fileName(), - result.m_projectPart, - true); - - // Make the symbol available in the database. - m_index.insertSymbol(symbol, result.m_unit->timeStamp()); - } - - // There might be files which were processed but did not "generate" any indexable symbol, - // but we still need to make the index aware of them. - result.m_processedFiles.insert(result.m_unit->fileName()); - foreach (const QString &fileName, result.m_processedFiles) { - if (!m_index.containsFile(fileName)) - m_index.insertFile(fileName, result.m_unit.timeStamp()); - } - - // If this unit is being kept alive, update in the manager. - if (LiveUnitsManager::instance()->isTracking(result.m_unit.fileName())) - LiveUnitsManager::instance()->updateUnit(result.m_unit.fileName(), result.m_unit); - } -#endif -} - -void IndexerPrivate::finished(LibClangIndexer *indexer) -{ - QMutexLocker locker(&m_mutex); - - m_runningIndexers.remove(indexer); - if (noIndexersRunning()) - indexingFinished(); -} - -bool IndexerPrivate::noIndexersRunning() const -{ - QMutexLocker locker(&m_mutex); - - return m_runningIndexers.isEmpty(); -} - -void IndexerPrivate::indexingFinished() -{ - if (m_hasQueuedFullRun) { - m_hasQueuedFullRun = false; - run(); - } else if (!m_queuedFilesRun.isEmpty()) { - const QStringList &files = m_queuedFilesRun.toList(); - m_queuedFilesRun.clear(); - run(files); - } - - emit m_q->indexingFinished(); -} - -void IndexerPrivate::cancelIndexing() -{ - QMutexLocker locker(&m_mutex); - - foreach (LibClangIndexer* partIndexer, m_runningIndexers) { - partIndexer->cancel(); - } -} - -int IndexerPrivate::runningIndexerCount() const -{ - QMutexLocker locker(&m_mutex); - return m_runningIndexers.size(); -} - -void IndexerPrivate::addOrUpdateFileData(const QString &fileName, - ProjectPart::Ptr projectPart, - bool upToDate) -{ - Q_ASSERT(QDir::isAbsolutePath(fileName)); - - QString cleanFileName(normalizeFileName(fileName)); - - FileType fileType = identifyFileType(cleanFileName); - if (isTrackingFile(cleanFileName, fileType)) { - m_files[fileType][cleanFileName].m_projectPart = projectPart; - m_files[fileType][cleanFileName].m_upToDate = upToDate; - } else { - m_files[fileType].insert(cleanFileName, - FileData(cleanFileName, projectPart, upToDate)); - } - - if (!upToDate) - m_index.removeFile(cleanFileName); -} - -bool IndexerPrivate::addFile(const QString &fileName, - ProjectPart::Ptr projectPart) -{ - if (isBusy() - || fileName.trimmed().isEmpty() - || !QFileInfo(fileName).isFile()) - return false; - - addOrUpdateFileData(fileName, projectPart, false); - - return true; -} - -QStringList IndexerPrivate::allFiles() const -{ - QStringList all; - populateFileNames(&all, m_files.at(ImplementationFile).values()); - populateFileNames(&all, m_files.at(HeaderFile).values()); - return all; -} - -bool IndexerPrivate::isTrackingFile(const QString &fileName, FileType type) const -{ - return m_files.value(type).contains(normalizeFileName(fileName)); -} - -QStringList IndexerPrivate::compilationOptions(const QString &fileName) const -{ - FileType type = identifyFileType(fileName); - return Utils::createClangOptions(m_files.value(type).value(normalizeFileName(fileName)).m_projectPart); -} - -IndexerPrivate::FileType IndexerPrivate::identifyFileType(const QString &fileName) -{ - const QString fn = fileName.toLower(); - if (fn.endsWith(QLatin1String(".cpp")) - || fn.endsWith(QLatin1String(".cxx")) - || fn.endsWith(QLatin1String(".cc")) - || fn.endsWith(QLatin1String(".c")) - || fn.endsWith(QLatin1String(".m")) - || fn.endsWith(QLatin1String(".mm"))) { - return ImplementationFile; - } - - // Everything that is not an implementation file is treated as a header. This makes things - // easier when handling standard library files and any other file that does not use - // conventional suffixes. - return HeaderFile; -} - -void IndexerPrivate::populateFileNames(QStringList *all, const QList<FileData> &data) -{ - foreach (const FileData &fileData, data) - all->append(fileData.m_fileName); -} - - -namespace { - -struct DepedencyVisitor -{ - DepedencyVisitor(IndexerPrivate *indexer) : m_indexer(indexer) {} - - bool acceptFile(const QString &includer) - { - IndexerPrivate::FileType fileType = IndexerPrivate::identifyFileType(includer); - if (m_indexer->isTrackingFile(includer, fileType)) { - m_match = m_indexer->m_files.at(fileType).value(includer); - return true; - } - return false; - } - - IndexerPrivate *m_indexer; - IndexerPrivate::FileData m_match; -}; - -} // Anonymous - -void IndexerPrivate::startLoading() -{ - // In the case of existent persisted symbols, we restore them and make them visible - // to the indexer. However, we need a dependency graph in order to identify the proper - // options. - - if (deserealizeSymbols() && !m_index.isEmpty()) - computeDependencyGraph(); - else - concludeLoading(); -} - -void IndexerPrivate::concludeLoading() -{ - m_isLoaded = true; - run(); -} - -void IndexerPrivate::computeDependencyGraph() -{ - // FIXME -// for (int fileType = ImplementationFile; fileType < TotalFileTypes; ++fileType) { -// QHash<QString, FileData>::iterator it = m_files[fileType].begin(); -// for (; it != m_files[fileType].end(); ++it) -// m_dependencyGraph.addFile(it.value().m_fileName, it.value().m_compilationOptions); -// } - - m_loadingWatcher.reset(new QFutureWatcher<void>); - connect(m_loadingWatcher.data(), SIGNAL(finished()), this, SLOT(dependencyGraphComputed())); -// m_loadingWatcher->setFuture(m_dependencyGraph.compute()); -} - -void IndexerPrivate::dependencyGraphComputed() -{ - if (m_loadingWatcher->isCanceled()) - return; - - m_loadingWatcher.reset(new QFutureWatcher<void>); - connect(m_loadingWatcher.data(), SIGNAL(finished()), this, SLOT(restoredSymbolsAnalysed())); - m_loadingWatcher->setFuture(QtConcurrent::run(this, &IndexerPrivate::analyzeRestoredSymbols)); -} - -void IndexerPrivate::analyzeRestoredSymbols() -{ - // @TODO: We only check for time stamps, so we still need to handle somehow the case in - // which the project options (for example a .pro file) changed while "outside" a Creator - // session. - - foreach (const QString &fileName, m_index.files()) { - bool upToDate = m_index.validate(fileName); - - FileType fileType = identifyFileType(fileName); - if (isTrackingFile(fileName, fileType)) { - // When the file is already being tracked we simply need to update its state. - if (upToDate) - m_files[fileType][fileName].m_upToDate = true; - } else { - // If it's not being tracked we need to find at least one tracked dependency - // so we can use its options. - DepedencyVisitor visitor(this); -// m_dependencyGraph.collectDependencies(fileName, -// DependencyGraph::FilesWhichInclude, -// &visitor); - if (!visitor.m_match.m_fileName.isEmpty()) { - addOrUpdateFileData(fileName, - visitor.m_match.m_projectPart, - upToDate); - } else { - m_index.removeFile(fileName); - } - } - - if (!upToDate && m_index.containsFile(fileName)) - m_index.removeFile(fileName); - } -} - -void IndexerPrivate::runQuickIndexing(const Unit::Ptr &unit, const CppTools::ProjectPart::Ptr &part) -{ - QMutexLocker locker(&m_mutex); - - addOrUpdateFileData(unit->fileName(), part, false); - - QuickIndexer indexer(this, unit, part); - indexer.run(); -} - -void IndexerPrivate::restoredSymbolsAnalysed() -{ - if (m_loadingWatcher->isCanceled()) - return; - - concludeLoading(); -} - -bool IndexerPrivate::deserealizeSymbols() -{ - if (m_storagePath.isEmpty()) - return false; - - ::Utils::FileReader reader; - if (reader.fetch(m_storagePath)) { - m_index.deserialize(reader.data()); - return true; - } - - return false; -} - -void IndexerPrivate::serializeSymbols() const -{ - if (m_storagePath.isEmpty()) - return; - - ::Utils::FileSaver saver(m_storagePath); - saver.write(m_index.serialize()); - if (!saver.finalize()) - qWarning("Failed to serialize index"); -} - -QList<Symbol> IndexerPrivate::symbols(Symbol::Kind kind) const -{ - if (m_loadingWatcher->isRunning()) - return QList<Symbol>(); - - return m_index.symbols(kind); -} - -QList<Symbol> IndexerPrivate::symbols(const QString &fileName, const Symbol::Kind kind) const -{ - if (m_loadingWatcher->isRunning()) - return QList<Symbol>(); - - if (kind == Symbol::Unknown) - return m_index.symbols(fileName); - - return m_index.symbols(fileName, kind); -} - -void IndexerPrivate::match(ClangSymbolSearcher *searcher) const -{ - if (m_loadingWatcher->isRunning()) - return; - - m_index.match(searcher); -} - -Indexer::Indexer(QObject *parent) - : QObject(parent) - , m_d(new IndexerPrivate(this)) -{} - -Indexer::~Indexer() -{} - -void Indexer::regenerate() -{ - if (!m_d->m_isLoaded) { - if (m_d->m_loadingWatcher->isRunning()) - return; - m_d->startLoading(); - } else { - m_d->run(); - } -} - -void Indexer::initialize(const QString &storagePath) -{ - Q_ASSERT(!m_d->m_isLoaded); - - m_d->m_storagePath = storagePath; -} - -void Indexer::evaluateFile(const QString &fileName) -{ - if (!m_d->m_isLoaded) - return; - - m_d->run(QStringList(normalizeFileName(fileName))); -} - -bool Indexer::isBusy() const -{ - return m_d->isBusy(); -} - -void Indexer::cancel(bool waitForFinished) -{ - return m_d->cancel(waitForFinished); -} - -void Indexer::finalize() -{ - m_d->reset(); -} - -bool Indexer::addFile(const QString &fileName, ProjectPart::Ptr projectPart) -{ - return m_d->addFile(fileName, projectPart); -} - -QStringList Indexer::allFiles() const -{ - return m_d->allFiles(); -} - -QStringList Indexer::compilationOptions(const QString &fileName) const -{ - return m_d->compilationOptions(fileName); -} - -QList<Symbol> Indexer::allFunctions() const -{ - return m_d->symbols(Symbol::Function); -} - -QList<Symbol> Indexer::allClasses() const -{ - return m_d->symbols(Symbol::Class); -} - -QList<Symbol> Indexer::allMethods() const -{ - return m_d->symbols(Symbol::Method); -} - -QList<Symbol> Indexer::allConstructors() const -{ - return m_d->symbols(Symbol::Constructor); -} - -QList<Symbol> Indexer::allDestructors() const -{ - return m_d->symbols(Symbol::Destructor); -} - -QList<Symbol> Indexer::functionsFromFile(const QString &fileName) const -{ - return m_d->symbols(fileName, Symbol::Function); -} - -QList<Symbol> Indexer::classesFromFile(const QString &fileName) const -{ - return m_d->symbols(fileName, Symbol::Class); -} - -QList<Symbol> Indexer::methodsFromFile(const QString &fileName) const -{ - return m_d->symbols(fileName, Symbol::Method); -} - -QList<Symbol> Indexer::constructorsFromFile(const QString &fileName) const -{ - return m_d->symbols(fileName, Symbol::Constructor); -} - -QList<Symbol> Indexer::destructorsFromFile(const QString &fileName) const -{ - return m_d->symbols(fileName, Symbol::Destructor); -} - -QList<Symbol> Indexer::allFromFile(const QString &fileName) const -{ - return m_d->symbols(fileName, Symbol::Unknown); -} - -void Indexer::match(ClangSymbolSearcher *searcher) const -{ - m_d->match(searcher); -} - -void Indexer::runQuickIndexing(Unit::Ptr unit, const CppTools::ProjectPart::Ptr &part) -{ - m_d->runQuickIndexing(unit, part); -} - -bool Indexer::isTracking(const QString &fileName) const -{ - return m_d->isTrackingFile(fileName, IndexerPrivate::ImplementationFile) - || m_d->isTrackingFile(fileName, IndexerPrivate::HeaderFile); -} - -#include "indexer.moc" diff --git a/src/plugins/clangcodemodel/indexer.h b/src/plugins/clangcodemodel/indexer.h deleted file mode 100644 index 5a1c435494..0000000000 --- a/src/plugins/clangcodemodel/indexer.h +++ /dev/null @@ -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. -** -****************************************************************************/ - -#ifndef INDEXER_H -#define INDEXER_H - -#include "clang_global.h" -#include "symbol.h" -#include "unit.h" - -#include <cpptools/cppmodelmanager.h> - -#include <QtCore/QObject> -#include <QtCore/QString> -#include <QtCore/QStringList> -#include <QtCore/QScopedPointer> -#include <QtCore/QFuture> - -namespace ClangCodeModel { - -namespace Internal { class ClangSymbolSearcher; } - -class IndexerPrivate; - -class CLANG_EXPORT Indexer : public QObject -{ - Q_OBJECT - -public: - typedef CppTools::ProjectPart ProjectPart; - -public: - Indexer(QObject *parent = 0); - ~Indexer(); - - void initialize(const QString &storagePath); - void finalize(); - - void regenerate(); - void evaluateFile(const QString &fileName); - bool isBusy() const; - void cancel(bool waitForFinished); - - bool addFile(const QString &fileName, ProjectPart::Ptr projectPart); - QStringList allFiles() const; - QStringList compilationOptions(const QString &fileName) const; - - QList<Symbol> allFunctions() const; - QList<Symbol> allClasses() const; - QList<Symbol> allMethods() const; - QList<Symbol> allConstructors() const; - QList<Symbol> allDestructors() const; - QList<Symbol> functionsFromFile(const QString &fileName) const; - QList<Symbol> classesFromFile(const QString &fileName) const; - QList<Symbol> methodsFromFile(const QString &fileName) const; - QList<Symbol> constructorsFromFile(const QString &fileName) const; - QList<Symbol> destructorsFromFile(const QString &fileName) const; - QList<Symbol> allFromFile(const QString &fileName) const; - - void match(Internal::ClangSymbolSearcher *searcher) const; - - void runQuickIndexing(Internal::Unit::Ptr unit, const ProjectPart::Ptr &part); - - bool isTracking(const QString &fileName) const; - -signals: - void indexingStarted(QFuture<void> future); - void indexingFinished(); - -private: - friend class IndexerPrivate; - QScopedPointer<IndexerPrivate> m_d; -}; - -} // ClangCodeModel - -#endif // INDEXER_H diff --git a/src/plugins/clangcodemodel/pchinfo.cpp b/src/plugins/clangcodemodel/pchinfo.cpp deleted file mode 100644 index a517d0f792..0000000000 --- a/src/plugins/clangcodemodel/pchinfo.cpp +++ /dev/null @@ -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; -} diff --git a/src/plugins/clangcodemodel/pchinfo.h b/src/plugins/clangcodemodel/pchinfo.h deleted file mode 100644 index ea542dc835..0000000000 --- a/src/plugins/clangcodemodel/pchinfo.h +++ /dev/null @@ -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 diff --git a/src/plugins/clangcodemodel/pchmanager.cpp b/src/plugins/clangcodemodel/pchmanager.cpp deleted file mode 100644 index 11cf0abcba..0000000000 --- a/src/plugins/clangcodemodel/pchmanager.cpp +++ /dev/null @@ -1,448 +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 "utils.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; - -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); -} diff --git a/src/plugins/clangcodemodel/pchmanager.h b/src/plugins/clangcodemodel/pchmanager.h deleted file mode 100644 index 1d6f4816d6..0000000000 --- a/src/plugins/clangcodemodel/pchmanager.h +++ /dev/null @@ -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 diff --git a/src/plugins/clangcodemodel/raii/scopedclangoptions.cpp b/src/plugins/clangcodemodel/raii/scopedclangoptions.cpp deleted file mode 100644 index 8d74d428d6..0000000000 --- a/src/plugins/clangcodemodel/raii/scopedclangoptions.cpp +++ /dev/null @@ -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 diff --git a/src/plugins/clangcodemodel/semanticmarker.cpp b/src/plugins/clangcodemodel/semanticmarker.cpp deleted file mode 100644 index 274e28e5ca..0000000000 --- a/src/plugins/clangcodemodel/semanticmarker.cpp +++ /dev/null @@ -1,531 +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 "semanticmarker.h" -#include "unit.h" -#include "utils_p.h" -#include "cxraii.h" - -#include <utils/mimetypes/mimedatabase.h> -#include <utils/qtcassert.h> - -using namespace ClangCodeModel; -using namespace ClangCodeModel::Internal; - -static const unsigned ATTACHED_NOTES_LIMIT = 10; - -SemanticMarker::SemanticMarker() -{ -} - -SemanticMarker::~SemanticMarker() -{ -} - -QString SemanticMarker::fileName() const -{ - if (!m_unit) - return QString(); - - return m_unit->fileName(); -} - -void SemanticMarker::setFileName(const QString &fileName) -{ - if (this->fileName() == fileName) - return; - - QStringList oldOptions; - if (m_unit) - oldOptions = m_unit->compilationOptions(); - m_unit = Unit::create(fileName); - if (!oldOptions.isEmpty()) - m_unit->setCompilationOptions(oldOptions); - - unsigned clangOpts = clang_defaultEditingTranslationUnitOptions(); - clangOpts |= CXTranslationUnit_DetailedPreprocessingRecord; - clangOpts |= CXTranslationUnit_Incomplete; - clangOpts &= ~CXTranslationUnit_CacheCompletionResults; - m_unit->setManagementOptions(clangOpts); -} - -void SemanticMarker::setCompilationOptions(const QStringList &options) -{ - QTC_ASSERT(m_unit, return); - - if (m_unit->compilationOptions() == options) - return; - - m_unit->setCompilationOptions(options); - m_unit->unload(); -} - -void SemanticMarker::reparse(const UnsavedFiles &unsavedFiles) -{ - QTC_ASSERT(m_unit, return); - - m_unit->setUnsavedFiles(unsavedFiles); - if (m_unit->isLoaded()) - m_unit->reparse(); - else - m_unit->parse(); -} - -/** - * \brief Calculate one or several ranges and append diagnostic for each range - * Extracted from SemanticMarker::diagnostics() to reuse code - */ -static void appendDiagnostic(const CXDiagnostic &diag, - const CXSourceLocation &cxLocation, - Diagnostic::Severity severity, - const QString &spelling, - QList<Diagnostic> &diagnostics) -{ - const unsigned rangeCount = clang_getDiagnosticNumRanges(diag); - bool expandLocation = true; - - for (unsigned i = 0; i < rangeCount; ++i) { - CXSourceRange r = clang_getDiagnosticRange(diag, i); - const SourceLocation &spellBegin = Internal::getSpellingLocation(clang_getRangeStart(r)); - const SourceLocation &spellEnd = Internal::getSpellingLocation(clang_getRangeEnd(r)); - unsigned length = spellEnd.offset() - spellBegin.offset(); - - // File name can be empty due clang bug - if (!spellBegin.fileName().isEmpty()) { - Diagnostic d(severity, spellBegin, length, spelling); - diagnostics.append(d); - expandLocation = false; - } - } - - if (expandLocation) { - const SourceLocation &location = Internal::getExpansionLocation(cxLocation); - Diagnostic d(severity, location, 0, spelling); - diagnostics.append(d); - } -} - -static bool isBlackListedDiagnostic(const Utils::MimeType &mimeType, const QString &diagnostic) -{ - static const QStringList blackList { - QLatin1String("#pragma once in main file"), - QLatin1String("#include_next in primary source file") - }; - - return mimeType.inherits(QLatin1String("text/x-chdr")) && blackList.contains(diagnostic); -} - -QList<Diagnostic> SemanticMarker::diagnostics() const -{ - QList<Diagnostic> diagnostics; - if (!m_unit || !m_unit->isLoaded()) - return diagnostics; - - Utils::MimeDatabase mimeDatabase; - const Utils::MimeType mimeType = mimeDatabase.mimeTypeForFile(fileName()); - - const unsigned diagCount = m_unit->getNumDiagnostics(); - for (unsigned i = 0; i < diagCount; ++i) { - ScopedCXDiagnostic diag(m_unit->getDiagnostic(i)); - - Diagnostic::Severity severity = static_cast<Diagnostic::Severity>(clang_getDiagnosticSeverity(diag)); - if (severity == Diagnostic::Ignored || severity == Diagnostic::Note) - continue; - - CXSourceLocation cxLocation = clang_getDiagnosticLocation(diag); - QString spelling = Internal::getQString(clang_getDiagnosticSpelling(diag)); - - if (isBlackListedDiagnostic(mimeType, spelling)) - continue; - - // Attach messages with Diagnostic::Note severity - ScopedCXDiagnosticSet cxChildren(clang_getChildDiagnostics(diag)); - const unsigned numChildren = clang_getNumDiagnosticsInSet(cxChildren); - const unsigned size = qMin(ATTACHED_NOTES_LIMIT, numChildren); - for (unsigned di = 0; di < size; ++di) { - ScopedCXDiagnostic child(clang_getDiagnosticInSet(cxChildren, di)); - - const Diagnostic::Severity severity - = static_cast<Diagnostic::Severity>(clang_getDiagnosticSeverity(child)); - if (severity == Diagnostic::Ignored || severity == Diagnostic::Note) - continue; - - spelling.append(QLatin1String("\n ")); - spelling.append(Internal::getQString(clang_getDiagnosticSpelling(child))); - } - - // Fatal error may occur in another file, but it breaks whole parsing - // Typical fatal error is unresolved #include - if (severity == Diagnostic::Fatal) { - for (unsigned di = 0; di < numChildren; ++di) { - ScopedCXDiagnostic child(clang_getDiagnosticInSet(cxChildren, di)); - appendDiagnostic(child, clang_getDiagnosticLocation(child), Diagnostic::Warning, spelling, diagnostics); - } - } - - appendDiagnostic(diag, cxLocation, severity, spelling, diagnostics); - } - - return diagnostics; -} - -QList<SemanticMarker::Range> SemanticMarker::ifdefedOutBlocks() const -{ - QList<Range> blocks; - - if (!m_unit || !m_unit->isLoaded()) - return blocks; - -#if CINDEX_VERSION_MINOR >= 21 - CXSourceRangeList *skippedRanges = clang_getSkippedRanges(m_unit->clangTranslationUnit(), - m_unit->getFile()); - blocks.reserve(skippedRanges->count); - for (unsigned i = 0; i < skippedRanges->count; ++i) { - const CXSourceRange &r = skippedRanges->ranges[i]; - const SourceLocation &spellBegin = Internal::getSpellingLocation(clang_getRangeStart(r)); - if (spellBegin.fileName() != fileName()) - continue; - const SourceLocation &spellEnd = Internal::getSpellingLocation(clang_getRangeEnd(r)); - const int begin = spellBegin.offset() + 1; - const int end = spellEnd.offset() - spellEnd.column(); - blocks.append(Range(begin, end)); - } - clang_disposeSourceRangeList(skippedRanges); -#endif - - return blocks; -} - -namespace { -static void add(QList<SourceMarker> &markers, - const CXSourceRange &extent, - SourceMarker::Kind kind) -{ - CXSourceLocation start = clang_getRangeStart(extent); - CXSourceLocation end = clang_getRangeEnd(extent); - const SourceLocation &location = Internal::getExpansionLocation(start); - const SourceLocation &locationEnd = Internal::getExpansionLocation(end); - - if (location.offset() < locationEnd.offset()) { - const unsigned length = locationEnd.offset() - location.offset(); - markers.append(SourceMarker(location, length, kind)); - } -} - -/** - * @brief Selects correct highlighting for cursor that is reference - * @return SourceMarker::Unknown if cannot select highlighting - */ -static SourceMarker::Kind getKindByReferencedCursor(const CXCursor &cursor) -{ - const CXCursor referenced = clang_getCursorReferenced(cursor); - switch (clang_getCursorKind(referenced)) { - case CXCursor_EnumConstantDecl: - return SourceMarker::Enumeration; - - case CXCursor_FieldDecl: - case CXCursor_ObjCIvarDecl: - case CXCursor_ObjCPropertyDecl: - return SourceMarker::Field; - - case CXCursor_FunctionDecl: - case CXCursor_FunctionTemplate: - case CXCursor_Constructor: - return SourceMarker::Function; - - case CXCursor_VarDecl: - case CXCursor_ParmDecl: - case CXCursor_NonTypeTemplateParameter: - return SourceMarker::Local; - - case CXCursor_CXXMethod: - if (clang_CXXMethod_isVirtual(referenced)) - return SourceMarker::VirtualMethod; - else - return SourceMarker::Function; - - case CXCursor_ObjCClassMethodDecl: - case CXCursor_ObjCInstanceMethodDecl: - // calling method as property, e.h. "layer.shouldRasterize = YES" - return SourceMarker::Field; - - case CXCursor_UnexposedDecl: - // NSObject "self" method which is a pseudo keyword - if (clang_getCursorLanguage(referenced) == CXLanguage_ObjC) - return SourceMarker::PseudoKeyword; - break; - - default: - break; - } - return SourceMarker::Unknown; -} - -static const QSet<QString> ObjcPseudoKeywords = QSet<QString>() - << QLatin1String("end") - << QLatin1String("try") - << QLatin1String("defs") - << QLatin1String("throw") - << QLatin1String("class") - << QLatin1String("catch") - << QLatin1String("encode") - << QLatin1String("public") - << QLatin1String("dynamic") - << QLatin1String("finally") - << QLatin1String("package") - << QLatin1String("private") - << QLatin1String("optional") - << QLatin1String("property") - << QLatin1String("protocol") - << QLatin1String("required") - << QLatin1String("selector") - << QLatin1String("interface") - << QLatin1String("protected") - << QLatin1String("synthesize") - << QLatin1String("not_keyword") - << QLatin1String("synchronized") - << QLatin1String("implementation") - << QLatin1String("compatibility_alias") - ; - -} // Anonymous namespace - -/** - * @brief SemanticMarker::sourceMarkersInRange - * @param firstLine - first line where to generate highlighting markers - * @param lastLine - last line where to generate highlighting markers - * - * There still two kinds of problems: - * - clang_annotateTokens() can return wrong cursor, and it's normal behavior - * - some cases no handled - * - * Problems caused by wrong cursors: - * - range-based for from C++ 2011 - * - identifiers in some compound statements have type DeclStmt - * or CompoundStmt which refers to top-level construction. - * - CXCursor_ObjCIvarDecl mapped to field, but instance variable have - * incorrect cursor kind if it declared in private interface - * @interface MyApplication() { - * NSArray* _items; - * } - * - * Missed cases: - * - global variables highlighted as locals - * - appropriate marker had not been selected for listed cursors: - * CXCursor_ObjCProtocolExpr, CXCursor_ObjCEncodeExpr, - * CXCursor_ObjCDynamicDecl, CXCursor_ObjCBridgedCastExpr, - * CXCursor_ObjCSuperClassRef - * - template members of template classes&functions always highlighted - * as members, even if they are functions - no way to differ found. - * - @1, @{}, @[] - */ -QList<SourceMarker> SemanticMarker::sourceMarkersInRange(unsigned firstLine, - unsigned lastLine) -{ - QList<SourceMarker> result; - - if (!m_unit || !m_unit->isLoaded()) - return result; - - // Highlighting called asynchronously, and a few lines at the end can be deleted for this time. - CXSourceRange unitRange = clang_getCursorExtent(m_unit->getTranslationUnitCursor()); - SourceLocation unitEnd = getExpansionLocation(clang_getRangeEnd(unitRange)); - if (lastLine > unitEnd.line()) - lastLine = unitEnd.line(); - - if (firstLine > lastLine) - return result; - - IdentifierTokens idTokens(*m_unit, firstLine, lastLine); - - const CXSourceRange *atTokenExtent = 0; - for (unsigned i = 0; i < idTokens.count(); ++i) { - const CXToken &tok = idTokens.token(i); - CXTokenKind kind = clang_getTokenKind(tok); - if (atTokenExtent) { - if (CXToken_Literal == kind) { - if (m_unit->getTokenSpelling(tok).startsWith(QLatin1Char('"'))) - add(result, *atTokenExtent, SourceMarker::ObjCString); - atTokenExtent = 0; - continue; - } else { - add(result, *atTokenExtent, SourceMarker::PseudoKeyword); - atTokenExtent = 0; - } - } - - const CXSourceRange &tokenExtent = idTokens.extent(i); - - if (CXToken_Keyword == kind) { - QString spell = m_unit->getTokenSpelling(tok); - if (ObjcPseudoKeywords.contains(spell)) - add(result, tokenExtent, SourceMarker::PseudoKeyword); - continue; - } - - if (CXToken_Punctuation == kind) { - static const QLatin1String at("@"); - if (m_unit->getTokenSpelling(tok) == at) - atTokenExtent = &tokenExtent; - continue; - } - - if (CXToken_Identifier != kind) - continue; - - const CXCursor &cursor = idTokens.cursor(i); - const CXCursorKind cursorKind = clang_getCursorKind(cursor); - if (clang_isInvalid(cursorKind)) - continue; - - switch (cursorKind) { - case CXCursor_EnumConstantDecl: - add(result, tokenExtent, SourceMarker::Enumeration); - break; - - case CXCursor_ClassDecl: - case CXCursor_UnionDecl: - case CXCursor_ClassTemplate: - case CXCursor_ClassTemplatePartialSpecialization: - case CXCursor_EnumDecl: - case CXCursor_Namespace: - case CXCursor_NamespaceRef: - case CXCursor_NamespaceAlias: - case CXCursor_StructDecl: - case CXCursor_TemplateRef: - case CXCursor_TypeRef: - case CXCursor_TypedefDecl: - case CXCursor_Constructor: - case CXCursor_TemplateTypeParameter: - case CXCursor_TemplateTemplateParameter: - case CXCursor_UnexposedDecl: /* friend class MyClass; */ - add(result, tokenExtent, SourceMarker::Type); - break; - - case CXCursor_ParmDecl: - case CXCursor_VariableRef: - case CXCursor_VarDecl: - case CXCursor_NonTypeTemplateParameter: - add(result, tokenExtent, SourceMarker::Local); - break; - - case CXCursor_MemberRefExpr: - case CXCursor_MemberRef: - case CXCursor_DeclRefExpr: - case CXCursor_CallExpr: { - SourceMarker::Kind kind = getKindByReferencedCursor(cursor); - if (kind == SourceMarker::Unknown && cursorKind == CXCursor_MemberRefExpr) { - /* template class member in template function */ - kind = SourceMarker::Field; - } - if (kind != SourceMarker::Unknown) - add(result, tokenExtent, kind); - } break; - - case CXCursor_FieldDecl: - add(result, tokenExtent, SourceMarker::Field); - break; - - case CXCursor_Destructor: - case CXCursor_CXXMethod: { - if (clang_CXXMethod_isVirtual(cursor)) - add(result, tokenExtent, SourceMarker::VirtualMethod); - else - add(result, tokenExtent, SourceMarker::Function); - } break; - - case CXCursor_CXXOverrideAttr: - case CXCursor_CXXFinalAttr: - case CXCursor_AnnotateAttr: // 'annotate' in '__attribute__((annotate("AnyComment")))' - case CXCursor_UnexposedAttr: // 'align' in '__declspec(align(8))' - add(result, tokenExtent, SourceMarker::PseudoKeyword); - break; - - case CXCursor_FunctionDecl: - case CXCursor_FunctionTemplate: - case CXCursor_OverloadedDeclRef: - add(result, tokenExtent, SourceMarker::Function); - break; - - case CXCursor_ObjCInstanceMethodDecl: - case CXCursor_ObjCClassMethodDecl: - case CXCursor_ObjCSelectorExpr: - add(result, tokenExtent, SourceMarker::ObjectiveCMessage); - break; - - case CXCursor_ObjCMessageExpr: { - static const QLatin1String super("super"); - if (m_unit->getTokenSpelling(tok) == super) - add(result, tokenExtent, SourceMarker::PseudoKeyword); - else - add(result, tokenExtent, SourceMarker::ObjectiveCMessage); - } break; - - case CXCursor_ObjCCategoryDecl: - case CXCursor_ObjCCategoryImplDecl: - case CXCursor_ObjCImplementationDecl: - case CXCursor_ObjCInterfaceDecl: - case CXCursor_ObjCProtocolDecl: - case CXCursor_ObjCProtocolRef: - case CXCursor_ObjCClassRef: - case CXCursor_ObjCSuperClassRef: - case CXCursor_TypeAliasDecl: // C++11 type alias: 'using value_t = T' - add(result, tokenExtent, SourceMarker::Type); - break; - - case CXCursor_ObjCSynthesizeDecl: - case CXCursor_ObjCDynamicDecl: - case CXCursor_ObjCPropertyDecl: - case CXCursor_ObjCIvarDecl: - add(result, tokenExtent, SourceMarker::Field); - break; - - case CXCursor_MacroDefinition: - case CXCursor_MacroExpansion: - add(result, tokenExtent, SourceMarker::Macro); - break; - - case CXCursor_LabelRef: - case CXCursor_LabelStmt: - add(result, tokenExtent, SourceMarker::Label); - break; - - default: - break; - } - } - - return result; -} - -Unit::Ptr SemanticMarker::unit() const -{ - return m_unit; -} diff --git a/src/plugins/clangcodemodel/semanticmarker.h b/src/plugins/clangcodemodel/semanticmarker.h deleted file mode 100644 index 238555b666..0000000000 --- a/src/plugins/clangcodemodel/semanticmarker.h +++ /dev/null @@ -1,95 +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_SEMANTICMARKER_H -#define CLANG_SEMANTICMARKER_H - -#include "clang_global.h" -#include "diagnostic.h" -#include "fastindexer.h" -#include "sourcemarker.h" -#include "utils.h" - -#include <QMutex> -#include <QScopedPointer> -#include <QSharedPointer> -#include <QString> -#include <QStringList> - -namespace ClangCodeModel { - -class CLANG_EXPORT SemanticMarker -{ - Q_DISABLE_COPY(SemanticMarker) - -public: - typedef QSharedPointer<SemanticMarker> Ptr; - - class Range - { - Range(); - public: - Range(int first, int last) : first(first), last(last) {} - - int first; - int last; - }; - -public: - SemanticMarker(); - ~SemanticMarker(); - - QMutex *mutex() const - { return &m_mutex; } - - QString fileName() const; - void setFileName(const QString &fileName); - - void setCompilationOptions(const QStringList &options); - - void reparse(const Internal::UnsavedFiles &unsavedFiles); - - QList<Diagnostic> diagnostics() const; - - QList<Range> ifdefedOutBlocks() const; - - QList<SourceMarker> sourceMarkersInRange(unsigned firstLine, - unsigned lastLine); - - Internal::Unit::Ptr unit() const; - -private: - mutable QMutex m_mutex; - Internal::Unit::Ptr m_unit; -}; - -} // namespace ClangCodeModel - -#endif // CLANG_SEMANTICMARKER_H diff --git a/src/plugins/clangcodemodel/sourcelocation.cpp b/src/plugins/clangcodemodel/sourcelocation.cpp deleted file mode 100644 index 2a48d4ed6c..0000000000 --- a/src/plugins/clangcodemodel/sourcelocation.cpp +++ /dev/null @@ -1,80 +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 "sourcelocation.h" - -using namespace ClangCodeModel; - -SourceLocation::SourceLocation() - : m_line(0) - , m_column(0) - , m_offset(0) -{} - -SourceLocation::SourceLocation(const QString &fileName, - unsigned line, - unsigned column, - unsigned offset) - : m_fileName(fileName) - , m_line(line) - , m_column(column) - , m_offset(offset) -{} - -namespace ClangCodeModel { - -bool operator==(const SourceLocation &a, const SourceLocation &b) -{ - return a.line() == b.line() - && a.column() == b.column() - && a.offset() == b.offset() - && a.fileName() == b.fileName() - ; -} - -bool operator!=(const SourceLocation &a, const SourceLocation &b) -{ - return !(a == b); -} - -QDebug operator<<(QDebug dbg, const SourceLocation &location) -{ - dbg.nospace() << location.fileName() - << " [" - << location.line() - << ":" - << location.column() - << "(" - << location.offset() - << ")]"; - return dbg.space(); -} - -} // ClangCodeModel diff --git a/src/plugins/clangcodemodel/sourcelocation.h b/src/plugins/clangcodemodel/sourcelocation.h deleted file mode 100644 index fab53ac720..0000000000 --- a/src/plugins/clangcodemodel/sourcelocation.h +++ /dev/null @@ -1,70 +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 SOURCELOCATION_H -#define SOURCELOCATION_H - -#include "clang_global.h" - -#include <QtCore/QString> -#include <QtCore/QDebug> - -namespace ClangCodeModel { - -class CLANG_EXPORT SourceLocation -{ -public: - SourceLocation(); - SourceLocation(const QString &fileName, - unsigned line = 0, - unsigned column = 0, - unsigned offset = 0); - - bool isNull() const { return m_fileName.isEmpty(); } - const QString &fileName() const { return m_fileName; } - unsigned line() const { return m_line; } - unsigned column() const { return m_column; } - unsigned offset() const { return m_offset; } - -private: - QString m_fileName; - unsigned m_line; - unsigned m_column; - unsigned m_offset; -}; - -bool operator==(const SourceLocation &a, const SourceLocation &b); -bool operator!=(const SourceLocation &a, const SourceLocation &b); - -QDebug operator<<(QDebug dbg, const SourceLocation &location); - -} // ClangCodeModel - -#endif // SOURCELOCATION_H diff --git a/src/plugins/clangcodemodel/sourcemarker.cpp b/src/plugins/clangcodemodel/sourcemarker.cpp deleted file mode 100644 index 3566bc4b1d..0000000000 --- a/src/plugins/clangcodemodel/sourcemarker.cpp +++ /dev/null @@ -1,42 +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 "sourcemarker.h" - -using namespace ClangCodeModel; - -SourceMarker::SourceMarker() - : m_length(0), m_kind(Unknown) -{} - -SourceMarker::SourceMarker(const SourceLocation &location, unsigned length, Kind kind) - : m_loc(location), m_length(length), m_kind(kind) -{ -} diff --git a/src/plugins/clangcodemodel/sourcemarker.h b/src/plugins/clangcodemodel/sourcemarker.h deleted file mode 100644 index eaf014ca52..0000000000 --- a/src/plugins/clangcodemodel/sourcemarker.h +++ /dev/null @@ -1,98 +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_SOURCEMARKER_H -#define CLANG_SOURCEMARKER_H - -#include "clang_global.h" -#include "sourcelocation.h" - -namespace ClangCodeModel { - -class CLANG_EXPORT SourceMarker -{ -public: // TODO: remove this, it's about the same as the TextEditor::SemanticHighlighter::Result - enum Kind { - Unknown = 0, - Type = 1, - Local, - Field, - Enumeration, - VirtualMethod, - Label, - Macro, - Function, - PseudoKeyword, - ObjCString, - - ObjectiveCMessage = VirtualMethod - }; - - SourceMarker(); - SourceMarker(const SourceLocation &location, - unsigned length, - Kind kind); - - bool isValid() const - { return m_loc.line() != 0; } - - bool isInvalid() const - { return m_loc.line() == 0; } - - const SourceLocation &location() const - { return m_loc; } - - unsigned length() const - { return m_length; } - - Kind kind() const - { return m_kind; } - - bool lessThan(const SourceMarker &other) const - { - if (m_loc.line() != other.m_loc.line()) - return m_loc.line() < other.m_loc.line(); - if (m_loc.column() != other.m_loc.column()) - return m_loc.column() < other.m_loc.column(); - return m_length < other.m_length; - } - -private: - SourceLocation m_loc; - unsigned m_length; - Kind m_kind; -}; - -CLANG_EXPORT inline bool operator<(const SourceMarker &one, const SourceMarker &two) -{ return one.lessThan(two); } - -} // namespace Clang - -#endif // CLANG_SOURCEMARKER_H diff --git a/src/plugins/clangcodemodel/symbol.cpp b/src/plugins/clangcodemodel/symbol.cpp deleted file mode 100644 index b37270c745..0000000000 --- a/src/plugins/clangcodemodel/symbol.cpp +++ /dev/null @@ -1,118 +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 "symbol.h" - -#include <cplusplus/Icons.h> - -using namespace ClangCodeModel; - -Symbol::Symbol() - : m_kind(Unknown) -{} - -Symbol::Symbol(const QString &name, - const QString &qualification, - Kind type, - const SourceLocation &location) - : m_name(name) - , m_qualification(qualification) - , m_location(location) - , m_kind(type) -{} - -QIcon Symbol::iconForSymbol() const -{ - CPlusPlus::Icons icons; - switch (m_kind) { - case Enum: - return icons.iconForType(CPlusPlus::Icons::EnumIconType); - case Class: - return icons.iconForType(CPlusPlus::Icons::ClassIconType); - case Method: - case Function: - case Declaration: - case Constructor: - case Destructor: - return icons.iconForType(CPlusPlus::Icons::FuncPublicIconType); - default: - return icons.iconForType(CPlusPlus::Icons::UnknownIconType); - } -} - -namespace ClangCodeModel { - -QDataStream &operator<<(QDataStream &stream, const Symbol &symbol) -{ - stream << symbol.m_name - << symbol.m_qualification - << symbol.m_location.fileName() - << (quint32)symbol.m_location.line() - << (quint16)symbol.m_location.column() - << (quint32)symbol.m_location.offset() - << (qint8)symbol.m_kind; - - return stream; -} - -QDataStream &operator>>(QDataStream &stream, Symbol &symbol) -{ - QString fileName; - quint32 line; - quint16 column; - quint32 offset; - quint8 kind; - stream >> symbol.m_name - >> symbol.m_qualification - >> fileName - >> line - >> column - >> offset - >> kind; - symbol.m_location = SourceLocation(fileName, line, column, offset); - symbol.m_kind = Symbol::Kind(kind); - - return stream; -} - -bool operator==(const Symbol &a, const Symbol &b) -{ - return a.m_name == b.m_name - && a.m_qualification == b.m_qualification - && a.m_location == b.m_location - && a.m_kind == b.m_kind; -} - -bool operator!=(const Symbol &a, const Symbol &b) -{ - return !(a == b); -} - -} // ClangCodeModel diff --git a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp index 857bf3b407..02acb42c5e 100644 --- a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp +++ b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp @@ -179,7 +179,7 @@ bool writeFile(const QString &filePath, const QByteArray &contents) void insertTextAtTopOfEditor(TextEditor::BaseTextEditor *editor, const QByteArray &text) { QTC_ASSERT(editor, return); - Utils::ChangeSet cs; + ::Utils::ChangeSet cs; cs.insert(0, QString::fromUtf8(text)); QTextCursor textCursor = editor->textCursor(); cs.apply(&textCursor); @@ -380,6 +380,16 @@ QString toString(const RequestDiagnosticsMessage &) return QStringLiteral("RequestDiagnosticsMessage\n"); } +QString toString(const RequestHighlightingMessage &) +{ + return QStringLiteral("RequestHighlightingMessage\n"); +} + +QString toString(const UpdateVisibleTranslationUnitsMessage &) +{ + return QStringLiteral("UpdateVisibleTranslationUnitsMessage\n"); +} + class IpcSenderSpy : public IpcSenderInterface { public: @@ -413,6 +423,11 @@ public: void requestDiagnostics(const RequestDiagnosticsMessage &message) override { senderLog.append(toString(message)); } + void requestHighlighting(const RequestHighlightingMessage &message) override + { senderLog.append(toString(message)); } + + void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override + { senderLog.append(toString(message)); } public: QString senderLog; @@ -1048,6 +1063,8 @@ void ClangCodeCompletionTest::testCompleteProjectDependingCodeInGeneratedUiFile( void ClangCodeCompletionTest::testCompleteAfterModifyingIncludedHeaderInOtherEditor() { + QSKIP("We don't reparse anymore before a code completion so we get wrong completion results."); + CppTools::Tests::TemporaryDir temporaryDir; const TestDocument sourceDocument("mysource.cpp", &temporaryDir); QVERIFY(sourceDocument.isCreatedAndHasValidCursorPosition()); @@ -1067,6 +1084,7 @@ void ClangCodeCompletionTest::testCompleteAfterModifyingIncludedHeaderInOtherEdi // Switch back to source file and check if modified header is reflected in completions. Core::EditorManager::activateEditor(openSource.editor()); + QCoreApplication::processEvents(); // connections are queued proposal = completionResults(openSource.editor()); QVERIFY(hasItem(proposal, "globalFromHeader")); QVERIFY(hasItem(proposal, "globalFromHeaderUnsaved")); @@ -1074,6 +1092,8 @@ void ClangCodeCompletionTest::testCompleteAfterModifyingIncludedHeaderInOtherEdi void ClangCodeCompletionTest::testCompleteAfterModifyingIncludedHeaderByRefactoringActions() { + QSKIP("We don't reparse anymore before a code completion so we get wrong completion results."); + CppTools::Tests::TemporaryDir temporaryDir; const TestDocument sourceDocument("mysource.cpp", &temporaryDir); QVERIFY(sourceDocument.isCreatedAndHasValidCursorPosition()); @@ -1092,7 +1112,7 @@ void ClangCodeCompletionTest::testCompleteAfterModifyingIncludedHeaderByRefactor // Modify header document without switching to its editor. // This simulates e.g. changes from refactoring actions. - Utils::ChangeSet cs; + ::Utils::ChangeSet cs; cs.insert(0, QLatin1String("int globalFromHeaderUnsaved;\n")); QTextCursor textCursor = openHeader.editor()->textCursor(); cs.apply(&textCursor); diff --git a/src/plugins/clangcodemodel/unit.cpp b/src/plugins/clangcodemodel/unit.cpp deleted file mode 100644 index 89e8963bf2..0000000000 --- a/src/plugins/clangcodemodel/unit.cpp +++ /dev/null @@ -1,357 +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 "utils_p.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); -} - -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); - 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::codeCompleteAt(unsigned line, unsigned column, ScopedCXCodeCompleteResults &results) -{ - unsigned flags = clang_defaultCodeCompleteOptions(); -#if defined(CINDEX_VERSION) && (CINDEX_VERSION > 5) - flags |= CXCodeComplete_IncludeBriefComments; -#endif - - UnsavedFileData unsaved(m_unsaved); - results.reset(clang_codeCompleteAt(m_tu, m_fileName.constData(), - line, column, - unsaved.files(), unsaved.count(), - flags)); -} - -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; -} - -QString Unit::getTokenSpelling(const CXToken &tok) const -{ - Q_ASSERT(isLoaded()); - - return getQString(clang_getTokenSpelling(m_tu, tok)); -} - -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; - } -} diff --git a/src/plugins/clangcodemodel/unit.h b/src/plugins/clangcodemodel/unit.h deleted file mode 100644 index 2506dc24fe..0000000000 --- a/src/plugins/clangcodemodel/unit.h +++ /dev/null @@ -1,200 +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 "utils.h" -#include "raii/scopedclangoptions.h" -#include "cxraii.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); - - UnsavedFiles unsavedFiles() const; - void setUnsavedFiles(const 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 codeCompleteAt(unsigned line, unsigned column, ScopedCXCodeCompleteResults &results); - - 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; - - QString getTokenSpelling(const CXToken &tok) const; - -private: - 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 -{ - 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 diff --git a/src/plugins/clangcodemodel/unsavedfiledata.cpp b/src/plugins/clangcodemodel/unsavedfiledata.cpp deleted file mode 100644 index 7dd54c6db2..0000000000 --- a/src/plugins/clangcodemodel/unsavedfiledata.cpp +++ /dev/null @@ -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; -} diff --git a/src/plugins/clangcodemodel/unsavedfiledata.h b/src/plugins/clangcodemodel/unsavedfiledata.h deleted file mode 100644 index c07753854d..0000000000 --- a/src/plugins/clangcodemodel/unsavedfiledata.h +++ /dev/null @@ -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 "utils.h" - -#include <clang-c/Index.h> - -namespace ClangCodeModel { -namespace Internal { - -class UnsavedFileData -{ - UnsavedFileData(const UnsavedFileData &); - UnsavedFileData &operator=(const UnsavedFileData &); - - typedef ClangCodeModel::Internal::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 diff --git a/src/plugins/clangcodemodel/utils.cpp b/src/plugins/clangcodemodel/utils.cpp deleted file mode 100644 index e7505f5211..0000000000 --- a/src/plugins/clangcodemodel/utils.cpp +++ /dev/null @@ -1,90 +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 "diagnostic.h" -#include "unit.h" -#include "utils.h" -#include "utils_p.h" - -#include <clang-c/Index.h> - -#include <QMutex> -#include <QMutexLocker> - -namespace ClangCodeModel { -namespace Internal { - -QPair<bool, QStringList> precompile(const PchInfo::Ptr &pchInfo) -{ -// qDebug() << "*** Precompiling" << pchInfo->inputFileName() -// << "into" << pchInfo->fileName() -// << "with options" << pchInfo->options(); - - bool ok = false; - - Internal::Unit::Ptr unit = Internal::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, Internal::formattedDiagnostics(unit)); -} - -namespace { -static bool clangInitialised = false; -static QMutex initialisationMutex; -} // anonymous namespace - -void initializeClang() -{ - if (clangInitialised) - return; - - QMutexLocker locker(&initialisationMutex); - if (clangInitialised) - return; - - clang_toggleCrashRecovery(1); - clang_enableStackTraces(); - clangInitialised = true; - - qRegisterMetaType<ClangCodeModel::Diagnostic>(); - qRegisterMetaType<QList<ClangCodeModel::Diagnostic> >(); -} - -} // Internal namespace -} // ClangCodeModel namespace - diff --git a/src/plugins/clangcodemodel/utils.h b/src/plugins/clangcodemodel/utils.h deleted file mode 100644 index 4126e48eb3..0000000000 --- a/src/plugins/clangcodemodel/utils.h +++ /dev/null @@ -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 UTILS_H -#define UTILS_H - -#include "pchinfo.h" - -#include <QString> -#include <QStringList> -#include <QByteArray> -#include <QMap> -#include <QPair> - -/* - * A header for globally visible typedefs. This is particularly useful - * so we don't have to #include files simply because of a typedef. Still, - * not every typedef should go in here, only the minimal subset of the - * ones which are needed quite often. - */ -namespace ClangCodeModel { -namespace Internal { - -typedef QMap<QString, QByteArray> UnsavedFiles; - -/** - * 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); - -void initializeClang(); - -} // Internal namespace -} // ClangCodeModel namespace - -#endif // UTILS_H diff --git a/src/plugins/clangcodemodel/utils_p.cpp b/src/plugins/clangcodemodel/utils_p.cpp deleted file mode 100644 index 07cec0e523..0000000000 --- a/src/plugins/clangcodemodel/utils_p.cpp +++ /dev/null @@ -1,125 +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 "utils_p.h" - -#include <QtCore/QDir> -#include <QtCore/QFileInfo> - -namespace ClangCodeModel { -namespace Internal { - -QString getQString(const CXString &cxString, bool disposeCXString) -{ - QString s = QString::fromUtf8(clang_getCString(cxString)); - if (disposeCXString) - clang_disposeString(cxString); - return s; -} - -namespace { - -SourceLocation getLocation(const CXSourceLocation &loc, - void (*clangFunction)(CXSourceLocation, - CXFile *, - unsigned *, - unsigned *, - unsigned *)) -{ - CXFile file; - unsigned line, column, offset; - (*clangFunction)(loc, &file, &line, &column, &offset); - return SourceLocation(normalizeFileName(getQString(clang_getFileName(file))), - line, - column, - offset); -} - -} // Anonymous - -SourceLocation getInstantiationLocation(const CXSourceLocation &loc) -{ - return getLocation(loc, &clang_getInstantiationLocation); -} - -SourceLocation getSpellingLocation(const CXSourceLocation &loc) -{ - return getLocation(loc, &clang_getSpellingLocation); -} - -SourceLocation getExpansionLocation(const CXSourceLocation &loc) -{ -// return getLocation(loc, &clang_getExpansionLocation); - return getLocation(loc, &clang_getInstantiationLocation); -} - -QString normalizeFileName(const QString &fileName) -{ - if (fileName.isEmpty()) - return fileName; - - return normalizeFileName(QFileInfo(fileName)); -} - -QString normalizeFileName(const QFileInfo &fileInfo) -{ - if (!fileInfo.isFile()) - return QString(); - - return QDir::cleanPath(fileInfo.absoluteFilePath()); -} - -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; -} - -} // Internal -} // ClangCodeModel diff --git a/src/plugins/clangcodemodel/utils_p.h b/src/plugins/clangcodemodel/utils_p.h deleted file mode 100644 index ea0f2837b1..0000000000 --- a/src/plugins/clangcodemodel/utils_p.h +++ /dev/null @@ -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_REUSE_H -#define CLANG_REUSE_H - -#include "sourcelocation.h" -#include "unit.h" - -#include <clang-c/Index.h> - -#include <QtCore/QString> - -QT_BEGIN_NAMESPACE -class QFileInfo; -QT_END_NAMESPACE - -namespace ClangCodeModel { -namespace Internal { - -QString getQString(const CXString &cxString, bool disposeCXString = true); - -SourceLocation getInstantiatonLocation(const CXSourceLocation &loc); // Deprecated -SourceLocation getSpellingLocation(const CXSourceLocation &loc); -SourceLocation getExpansionLocation(const CXSourceLocation &loc); - -// There are slight differences of behavior from apparently similar Qt file processing functions. -// For instance, QFileInfo::absoluteFilePath will uppercase driver letters, while the corresponding -// QDir function will not do so. Besides, we need to keep paths clean. So in order to avoid -// inconsistencies the functions below should be used for any indexing related task. -QString normalizeFileName(const QString &fileName); -QString normalizeFileName(const QFileInfo &fileInfo); - -QStringList formattedDiagnostics(const Unit::Ptr &unit); - -} // Internal -} // ClangCodeModel - -#endif // CLANG_REUSE_H diff --git a/src/plugins/cppeditor/cppeditordocument.cpp b/src/plugins/cppeditor/cppeditordocument.cpp index 3c52ad0ef3..e74aa05c46 100644 --- a/src/plugins/cppeditor/cppeditordocument.cpp +++ b/src/plugins/cppeditor/cppeditordocument.cpp @@ -63,8 +63,7 @@ CppTools::CppModelManager *mm() namespace CppEditor { namespace Internal { -enum { processDocumentIntervalInMs = 150, - clangProcessDocumentIntervalInMs = 500 }; +enum { processDocumentIntervalInMs = 150 }; class CppEditorDocumentHandleImpl : public CppTools::CppEditorDocumentHandle { @@ -292,10 +291,7 @@ void CppEditorDocument::releaseResources() void CppEditorDocument::initializeTimer() { m_processorTimer.setSingleShot(true); - if (mm()->isClangCodeModelActive()) - m_processorTimer.setInterval(clangProcessDocumentIntervalInMs); - else - m_processorTimer.setInterval(processDocumentIntervalInMs); + m_processorTimer.setInterval(processDocumentIntervalInMs); connect(&m_processorTimer, &QTimer::timeout, diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 079de7cfdd..7a94dbb580 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -936,7 +936,7 @@ ProjectPart::Ptr CppModelManager::fallbackProjectPart() return part; } -bool CppModelManager::isCppEditor(Core::IEditor *editor) const +bool CppModelManager::isCppEditor(Core::IEditor *editor) { return editor->context().contains(ProjectExplorer::Constants::LANG_CXX); } diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h index dac3973bce..4c10343eda 100644 --- a/src/plugins/cpptools/cppmodelmanager.h +++ b/src/plugins/cpptools/cppmodelmanager.h @@ -91,6 +91,7 @@ public: QFuture<void> updateSourceFiles(const QSet<QString> &sourceFiles, ProgressNotificationMode mode = ReservedProgressNotification); + void updateCppEditorDocuments() const; WorkingCopy workingCopy() const; QByteArray codeModelConfiguration() const; @@ -120,7 +121,7 @@ public: const QByteArray &contents); void emitAbstractEditorSupportRemoved(const QString &filePath); - bool isCppEditor(Core::IEditor *editor) const; + static bool isCppEditor(Core::IEditor *editor); bool isClangCodeModelAvailable() const; bool isClangCodeModelActive() const; @@ -209,7 +210,6 @@ private: void initializeModelManagerSupports(); void delayedGC(); void recalculateProjectPartMappings(); - void updateCppEditorDocuments() const; void replaceSnapshot(const CPlusPlus::Snapshot &newSnapshot); void removeFilesFromSnapshot(const QSet<QString> &removedFiles); diff --git a/src/plugins/cpptools/cppprojects.h b/src/plugins/cpptools/cppprojects.h index a63f557587..3d8ddba0be 100644 --- a/src/plugins/cpptools/cppprojects.h +++ b/src/plugins/cpptools/cppprojects.h @@ -247,6 +247,4 @@ private: } // namespace CppTools -Q_DECLARE_METATYPE(CppTools::ProjectPart::Ptr) - #endif // CPPPROJECTPART_H diff --git a/src/plugins/cpptools/cpptools_global.h b/src/plugins/cpptools/cpptools_global.h index 57b5dbab70..b30e9e2919 100644 --- a/src/plugins/cpptools/cpptools_global.h +++ b/src/plugins/cpptools/cpptools_global.h @@ -35,6 +35,8 @@ #if defined(CPPTOOLS_LIBRARY) # define CPPTOOLS_EXPORT Q_DECL_EXPORT +#elif defined(CPPTOOLS_STATIC_LIBRARY) +# define CPPTOOLS_EXPORT #else # define CPPTOOLS_EXPORT Q_DECL_IMPORT #endif diff --git a/src/plugins/cpptools/cpptoolsunittestfiles.pri b/src/plugins/cpptools/cpptoolsunittestfiles.pri index 6e0ab0d990..2d011718e6 100644 --- a/src/plugins/cpptools/cpptoolsunittestfiles.pri +++ b/src/plugins/cpptools/cpptoolsunittestfiles.pri @@ -1,3 +1,9 @@ +contains(CONFIG, dll) { + DEFINES += CPPTOOLS_LIBRARY +} else { + DEFINES += CPPTOOLS_STATIC_LIBRARY +} + HEADERS += $$PWD/senddocumenttracker.h SOURCES += $$PWD/senddocumenttracker.cpp diff --git a/src/plugins/debugger/debuggerprotocol.cpp b/src/plugins/debugger/debuggerprotocol.cpp index 35c2d220f3..4a1a7574b4 100644 --- a/src/plugins/debugger/debuggerprotocol.cpp +++ b/src/plugins/debugger/debuggerprotocol.cpp @@ -843,19 +843,47 @@ void DebuggerCommand::arg(const char *value) args = arr; } +void DebuggerCommand::arg(const char *name, bool value) +{ + args = addToJsonObject(args, name, value); +} + void DebuggerCommand::arg(const char *name, const QJsonValue &value) { args = addToJsonObject(args, name, value); } -QByteArray DebuggerCommand::argsToPython() const +static QJsonValue translateJsonToPython(const QJsonValue &value) { - // TODO: Verify that this is really Python. + // TODO: Verify that this covers all incompatibilities between python and json. + switch (value.type()) { + case QJsonValue::Bool: + // Python doesn't understand lowercase "true" or "false" + return QJsonValue(value.toBool() ? 1 : 0); + case QJsonValue::Object: { + QJsonObject object = value.toObject(); + for (QJsonObject::iterator i = object.begin(); i != object.end(); ++i) + i.value() = translateJsonToPython(i.value()); + return object; + } + case QJsonValue::Array: { + QJsonArray array = value.toArray(); + for (QJsonArray::iterator i = array.begin(); i != array.end(); ++i) + *i = translateJsonToPython(*i); + return array; + } + default: + return value; + } +} - if (args.isArray()) - return QJsonDocument(args.toArray()).toJson(QJsonDocument::Compact); +QByteArray DebuggerCommand::argsToPython() const +{ + QJsonValue pythonCompatible(translateJsonToPython(args)); + if (pythonCompatible.isArray()) + return QJsonDocument(pythonCompatible.toArray()).toJson(QJsonDocument::Compact); else - return QJsonDocument(args.toObject()).toJson(QJsonDocument::Compact); + return QJsonDocument(pythonCompatible.toObject()).toJson(QJsonDocument::Compact); } QByteArray DebuggerCommand::argsToString() const diff --git a/src/plugins/debugger/debuggerprotocol.h b/src/plugins/debugger/debuggerprotocol.h index f85746a006..d7849a5b92 100644 --- a/src/plugins/debugger/debuggerprotocol.h +++ b/src/plugins/debugger/debuggerprotocol.h @@ -58,6 +58,7 @@ public: DebuggerCommand(const QByteArray &f, int fl, const Callback &cb) : function(f), callback(cb), flags(fl) {} void arg(const char *value); + void arg(const char *name, bool value); void arg(const char *name, int value); void arg(const char *name, qlonglong value); void arg(const char *name, qulonglong value); diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 9d290e8c2c..e907522ff8 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -354,10 +354,8 @@ void QmlEngine::tryToConnect(quint16 port) if (state() == EngineRunRequested) { if (isSlaveEngine()) { // Probably cpp is being debugged and hence we did not get the output yet. - if (!masterEngine()->isDying()) { - d->noDebugOutputTimer.setInterval(4000); - d->noDebugOutputTimer.start(); - } + if (!masterEngine()->isDying()) + beginConnection(port); else appStartupFailed(tr("No application output received in time")); } else { diff --git a/src/plugins/projectexplorer/toolchainmanager.cpp b/src/plugins/projectexplorer/toolchainmanager.cpp index bb8502a373..8cd26fe1e5 100644 --- a/src/plugins/projectexplorer/toolchainmanager.cpp +++ b/src/plugins/projectexplorer/toolchainmanager.cpp @@ -203,11 +203,21 @@ static bool containsByEqual(const QList<ToolChain *> &a, const ToolChain *atc) return Utils::anyOf(a, [atc](ToolChain *btc) { return *atc == *btc; }); } -static QList<ToolChain *> makeUnique(const QList<ToolChain *> &a) +static QList<ToolChain *> makeUniqueByPointerEqual(const QList<ToolChain *> &a) { return QSet<ToolChain *>::fromList(a).toList(); } +static QList<ToolChain *> makeUniqueByEqual(const QList<ToolChain *> &a) +{ + QList<ToolChain *> result; + foreach (ToolChain *tc, a) { + if (!Utils::contains(result, [tc](ToolChain *rtc) { return *tc == *rtc; })) + result.append(tc); + } + return result; +} + namespace { struct ToolChainOperations @@ -223,11 +233,11 @@ static ToolChainOperations mergeToolChainLists(const QList<ToolChain *> &systemF const QList<ToolChain *> &userFileTcs, const QList<ToolChain *> &autodetectedTcs) { - // Remove systemFileTcs from autodetectedUserFileTcs based on id-matches: + const QList<ToolChain *> uniqueUserFileTcs = makeUniqueByEqual(userFileTcs); QList<ToolChain *> manualUserFileTcs; QList<ToolChain *> autodetectedUserFileTcs; std::tie(autodetectedUserFileTcs, manualUserFileTcs) - = Utils::partition(userFileTcs, &ToolChain::isAutoDetected); + = Utils::partition(uniqueUserFileTcs, &ToolChain::isAutoDetected); const QList<ToolChain *> autodetectedUserTcs = subtractById(autodetectedUserFileTcs, systemFileTcs); // Calculate a set of Tcs that were detected before (and saved to userFile) and that @@ -253,8 +263,8 @@ static ToolChainOperations mergeToolChainLists(const QList<ToolChain *> &systemF result.toRegister = systemFileTcs + validManualUserTcs + result.toDemote // manual TCs + redetectedUserTcs + newlyAutodetectedTcs; // auto TCs - result.toDelete = makeUnique(subtractByPointerEqual(systemFileTcs + userFileTcs + autodetectedTcs, - result.toRegister)); + result.toDelete = makeUniqueByPointerEqual(subtractByPointerEqual(systemFileTcs + userFileTcs + autodetectedTcs, + result.toRegister)); return result; } @@ -540,6 +550,9 @@ void ProjectExplorerPlugin::testToolChainManager_data() QTest::newRow("Auto: auto-redetect, user") << (TCList()) << (TCList() << auto1) << (TCList() << auto1_2) << (TCList()) << (TCList() << auto1); + QTest::newRow("Auto: auto-redetect, duplicate users") + << (TCList()) << (TCList() << auto1 << auto1c) << (TCList() << auto1_2) + << (TCList()) << (TCList() << auto1); QTest::newRow("Auto: (no) auto, invalid user") << (TCList()) << (TCList() << auto3i) << (TCList()) << (TCList()) << (TCList()); diff --git a/src/plugins/texteditor/codeassist/codeassistant.cpp b/src/plugins/texteditor/codeassist/codeassistant.cpp index cc247d1323..59fe46e5e3 100644 --- a/src/plugins/texteditor/codeassist/codeassistant.cpp +++ b/src/plugins/texteditor/codeassist/codeassistant.cpp @@ -263,14 +263,8 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason, case IAssistProvider::Asynchronous: { processor->setAsyncCompletionAvailableHandler( [this, processor, reason](IAssistProposal *newProposal){ - if (m_asyncProcessor != processor) { - delete newProposal->model(); - delete newProposal; - return; - } - - invalidateCurrentRequestData(); QTC_CHECK(newProposal); + invalidateCurrentRequestData(); displayProposal(newProposal, reason); emit q->finished(); @@ -282,10 +276,10 @@ void CodeAssistantPrivate::requestProposal(AssistReason reason, delete processor; } else if (!processor->performWasApplicable()) { delete processor; + } else { // ...async request was triggered + m_asyncProcessor = processor; } - // ...otherwise the async request was triggered - m_asyncProcessor = processor; break; } } // switch diff --git a/src/plugins/texteditor/codeassist/genericproposalwidget.cpp b/src/plugins/texteditor/codeassist/genericproposalwidget.cpp index 0c974729cc..063bedb956 100644 --- a/src/plugins/texteditor/codeassist/genericproposalwidget.cpp +++ b/src/plugins/texteditor/codeassist/genericproposalwidget.cpp @@ -440,9 +440,9 @@ void GenericProposalWidget::notifyActivation(int index) void GenericProposalWidget::abort() { + deleteLater(); if (isVisible()) close(); - deleteLater(); } bool GenericProposalWidget::updateAndCheck(const QString &prefix) diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp index cc28f20dc5..213f15cfcc 100644 --- a/src/plugins/texteditor/textdocument.cpp +++ b/src/plugins/texteditor/textdocument.cpp @@ -130,7 +130,7 @@ QTextCursor TextDocumentPrivate::indentOrUnindent(const QTextCursor &textCursor, bool modified = true; QTextBlock startBlock = m_document.findBlock(start); - QTextBlock endBlock = m_document.findBlock(end).next(); + QTextBlock endBlock = m_document.findBlock(blockSelection ? end : end - 1).next(); const bool oneLinePartial = (startBlock.next() == endBlock) && (start > startBlock.position() || end < endBlock.position() - 1); diff --git a/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri b/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri index 93131082bf..1724c5799c 100644 --- a/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri +++ b/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri @@ -3,7 +3,6 @@ INCLUDEPATH += $$PWD HEADERS += $$PWD/clangipcserver.h \ $$PWD/codecompleter.h \ $$PWD/clangstring.h \ - $$PWD/translationunit.h \ $$PWD/translationunitisnullexception.h \ $$PWD/codecompletefailedexception.h \ $$PWD/clangcodecompleteresults.h \ @@ -27,16 +26,16 @@ HEADERS += $$PWD/clangipcserver.h \ $$PWD/translationunitalreadyexistsexception.h \ $$PWD/commandlinearguments.h \ $$PWD/cursor.h \ - $$PWD/type.h \ $$PWD/highlightinginformations.h \ $$PWD/highlightinginformation.h \ $$PWD/highlightinginformationsiterator.h \ - $$PWD/skippedsourceranges.h + $$PWD/skippedsourceranges.h \ + $$PWD/clangtranslationunit.h \ + $$PWD/clangtype.h SOURCES += $$PWD/clangipcserver.cpp \ $$PWD/codecompleter.cpp \ $$PWD/clangstring.cpp \ - $$PWD/translationunit.cpp \ $$PWD/translationunitisnullexception.cpp \ $$PWD/codecompletefailedexception.cpp \ $$PWD/clangcodecompleteresults.cpp \ @@ -59,7 +58,8 @@ SOURCES += $$PWD/clangipcserver.cpp \ $$PWD/translationunitalreadyexistsexception.cpp \ $$PWD/commandlinearguments.cpp \ $$PWD/cursor.cpp \ - $$PWD/type.cpp \ $$PWD/highlightinginformations.cpp \ $$PWD/highlightinginformation.cpp \ - $$PWD/skippedsourceranges.cpp + $$PWD/skippedsourceranges.cpp \ + $$PWD/clangtranslationunit.cpp \ + $$PWD/clangtype.cpp diff --git a/src/tools/clangbackend/ipcsource/clangipcserver.cpp b/src/tools/clangbackend/ipcsource/clangipcserver.cpp index 31c3ae481f..7165ed24a5 100644 --- a/src/tools/clangbackend/ipcsource/clangipcserver.cpp +++ b/src/tools/clangbackend/ipcsource/clangipcserver.cpp @@ -33,7 +33,9 @@ #include "clangfilesystemwatcher.h" #include "codecompleter.h" #include "diagnosticset.h" +#include "highlightinginformations.h" #include "projectpartsdonotexistexception.h" +#include "skippedsourceranges.h" #include "translationunitdoesnotexistexception.h" #include "translationunitfilenotexitexception.h" #include "translationunitisnullexception.h" @@ -48,8 +50,10 @@ #include <cmbunregisterprojectsforeditormessage.h> #include <cmbunregistertranslationunitsforeditormessage.h> #include <diagnosticschangedmessage.h> +#include <highlightingchangedmessage.h> #include <registerunsavedfilesforeditormessage.h> #include <requestdiagnosticsmessage.h> +#include <requesthighlightingmessage.h> #include <projectpartsdonotexistmessage.h> #include <translationunitdoesnotexistmessage.h> #include <unregisterunsavedfilesforeditormessage.h> @@ -62,37 +66,66 @@ namespace ClangBackEnd { namespace { -const int sendDiagnosticsTimerInterval = 300; + +int getIntervalFromEnviromentVariable() +{ + const QByteArray userIntervalAsByteArray = qgetenv("QTC_CLANG_DELAYED_REPARSE_TIMEOUT"); + + bool isConversionOk = false; + const int intervalAsInt = userIntervalAsByteArray.toInt(&isConversionOk); + + if (isConversionOk) + return intervalAsInt; + else + return -1; +} + +int delayedDocumentAnnotationsTimerInterval() +{ + static const int defaultInterval = 1500; + static const int userDefinedInterval = getIntervalFromEnviromentVariable(); + static const int interval = userDefinedInterval >= 0 ? userDefinedInterval : defaultInterval; + + return interval; +} + } ClangIpcServer::ClangIpcServer() : translationUnits(projects, unsavedFiles) { - translationUnits.setSendChangeDiagnosticsCallback([this] (const DiagnosticsChangedMessage &message) - { - client()->diagnosticsChanged(message); - }); + const auto sendDocumentAnnotations + = [this] (const DiagnosticsChangedMessage &diagnosticsMessage, + const HighlightingChangedMessage &highlightingsMessage) { + client()->diagnosticsChanged(diagnosticsMessage); + client()->highlightingChanged(highlightingsMessage); + }; + + const auto sendDelayedDocumentAnnotations = [this] () { + try { + auto sendState = translationUnits.sendDocumentAnnotations(); + if (sendState == DocumentAnnotationsSendState::MaybeThereAreDocumentAnnotations) + sendDocumentAnnotationsTimer.setInterval(0); + else + sendDocumentAnnotationsTimer.stop(); + } catch (const std::exception &exception) { + qWarning() << "Error in ClangIpcServer::sendDelayedDocumentAnnotationsTimer:" << exception.what(); + } + }; + + const auto onFileChanged = [this] (const Utf8String &filePath) { + startDocumentAnnotationsTimerIfFileIsNotATranslationUnit(filePath); + }; - QObject::connect(&sendDiagnosticsTimer, + translationUnits.setSendDocumentAnnotationsCallback(sendDocumentAnnotations); + + QObject::connect(&sendDocumentAnnotationsTimer, &QTimer::timeout, - [this] () { - try { - auto diagnostSendState = translationUnits.sendChangedDiagnostics(); - if (diagnostSendState == DiagnosticSendState::MaybeThereAreMoreDiagnostics) - sendDiagnosticsTimer.setInterval(0); - else - sendDiagnosticsTimer.stop(); - } catch (const std::exception &exception) { - qWarning() << "Error in ClangIpcServer::sendDiagnosticsTimer:" << exception.what(); - } - }); + sendDelayedDocumentAnnotations); QObject::connect(translationUnits.clangFileSystemWatcher(), &ClangFileSystemWatcher::fileChanged, - [this] (const Utf8String &filePath) - { - startSendDiagnosticTimerIfFileIsNotATranslationUnit(filePath); - }); + onFileChanged); } void ClangIpcServer::end() @@ -105,9 +138,12 @@ void ClangIpcServer::registerTranslationUnitsForEditor(const ClangBackEnd::Regis TIME_SCOPE_DURATION("ClangIpcServer::registerTranslationUnitsForEditor"); try { - translationUnits.create(message.fileContainers()); + auto createdTranslationUnits = translationUnits.create(message.fileContainers()); unsavedFiles.createOrUpdate(message.fileContainers()); - sendDiagnosticsTimer.start(0); + translationUnits.setUsedByCurrentEditor(message.currentEditorFilePath()); + translationUnits.setVisibleInEditors(message.visibleEditorFilePaths()); + startDocumentAnnotations(); + reparseVisibleDocuments(createdTranslationUnits); } catch (const ProjectPartDoNotExistException &exception) { client()->projectPartsDoNotExist(ProjectPartsDoNotExistMessage(exception.projectPartIds())); } catch (const std::exception &exception) { @@ -124,7 +160,7 @@ void ClangIpcServer::updateTranslationUnitsForEditor(const UpdateTranslationUnit if (newerFileContainers.size() > 0) { translationUnits.update(newerFileContainers); unsavedFiles.createOrUpdate(newerFileContainers); - sendDiagnosticsTimer.start(sendDiagnosticsTimerInterval); + sendDocumentAnnotationsTimer.start(delayedDocumentAnnotationsTimerInterval()); } } catch (const ProjectPartDoNotExistException &exception) { client()->projectPartsDoNotExist(ProjectPartsDoNotExistMessage(exception.projectPartIds())); @@ -182,7 +218,7 @@ void ClangIpcServer::registerUnsavedFilesForEditor(const RegisterUnsavedFilesFor try { unsavedFiles.createOrUpdate(message.fileContainers()); translationUnits.updateTranslationUnitsWithChangedDependencies(message.fileContainers()); - sendDiagnosticsTimer.start(sendDiagnosticsTimerInterval); + sendDocumentAnnotationsTimer.start(delayedDocumentAnnotationsTimerInterval()); } catch (const ProjectPartDoNotExistException &exception) { client()->projectPartsDoNotExist(ProjectPartsDoNotExistMessage(exception.projectPartIds())); } catch (const std::exception &exception) { @@ -244,13 +280,34 @@ void ClangIpcServer::requestDiagnostics(const RequestDiagnosticsMessage &message } } +void ClangIpcServer::requestHighlighting(const RequestHighlightingMessage &message) +{ + TIME_SCOPE_DURATION("ClangIpcServer::requestHighlighting"); + + try { + auto translationUnit = translationUnits.translationUnit(message.fileContainer().filePath(), + message.fileContainer().projectPartId()); + + client()->highlightingChanged(HighlightingChangedMessage(translationUnit.fileContainer(), + translationUnit.highlightingInformations().toHighlightingMarksContainers(), + translationUnit.skippedSourceRanges().toSourceRangeContainers())); + } catch (const TranslationUnitDoesNotExistException &exception) { + client()->translationUnitDoesNotExist(TranslationUnitDoesNotExistMessage(exception.fileContainer())); + } catch (const ProjectPartDoNotExistException &exception) { + client()->projectPartsDoNotExist(ProjectPartsDoNotExistMessage(exception.projectPartIds())); + } catch (const std::exception &exception) { + qWarning() << "Error in ClangIpcServer::requestHighlighting:" << exception.what(); + } +} + void ClangIpcServer::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) { TIME_SCOPE_DURATION("ClangIpcServer::updateVisibleTranslationUnits"); try { - translationUnits.setCurrentEditor(message.currentEditorFilePath()); - translationUnits.setVisibleEditors(message.visibleEditorFilePaths()); + translationUnits.setUsedByCurrentEditor(message.currentEditorFilePath()); + translationUnits.setVisibleInEditors(message.visibleEditorFilePaths()); + sendDocumentAnnotationsTimer.start(0); } catch (const std::exception &exception) { qWarning() << "Error in ClangIpcServer::updateVisibleTranslationUnits:" << exception.what(); } @@ -261,10 +318,25 @@ const TranslationUnits &ClangIpcServer::translationUnitsForTestOnly() const return translationUnits; } -void ClangIpcServer::startSendDiagnosticTimerIfFileIsNotATranslationUnit(const Utf8String &filePath) +void ClangIpcServer::startDocumentAnnotationsTimerIfFileIsNotATranslationUnit(const Utf8String &filePath) { if (!translationUnits.hasTranslationUnit(filePath)) - sendDiagnosticsTimer.start(0); + sendDocumentAnnotationsTimer.start(0); +} + +void ClangIpcServer::startDocumentAnnotations() +{ + DocumentAnnotationsSendState sendState = DocumentAnnotationsSendState::MaybeThereAreDocumentAnnotations; + + while (sendState == DocumentAnnotationsSendState::MaybeThereAreDocumentAnnotations) + sendState = translationUnits.sendDocumentAnnotations(); +} + +void ClangIpcServer::reparseVisibleDocuments(std::vector<TranslationUnit> &translationUnits) +{ + for (TranslationUnit &translationUnit : translationUnits) + if (translationUnit.isVisibleInEditor()) + translationUnit.reparse(); } } diff --git a/src/tools/clangbackend/ipcsource/clangipcserver.h b/src/tools/clangbackend/ipcsource/clangipcserver.h index bfb1313e64..8fcbddc7a4 100644 --- a/src/tools/clangbackend/ipcsource/clangipcserver.h +++ b/src/tools/clangbackend/ipcsource/clangipcserver.h @@ -35,7 +35,7 @@ #include "projectpart.h" #include "projects.h" -#include "translationunit.h" +#include "clangtranslationunit.h" #include "translationunits.h" #include "unsavedfiles.h" @@ -61,18 +61,21 @@ public: void unregisterUnsavedFilesForEditor(const UnregisterUnsavedFilesForEditorMessage &message) override; void completeCode(const CompleteCodeMessage &message) override; void requestDiagnostics(const RequestDiagnosticsMessage &message) override; + void requestHighlighting(const RequestHighlightingMessage &message) override; void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override; const TranslationUnits &translationUnitsForTestOnly() const; private: - void startSendDiagnosticTimerIfFileIsNotATranslationUnit(const Utf8String &filePath); + void startDocumentAnnotationsTimerIfFileIsNotATranslationUnit(const Utf8String &filePath); + void startDocumentAnnotations(); + void reparseVisibleDocuments(std::vector<TranslationUnit> &translationUnits); private: ProjectParts projects; UnsavedFiles unsavedFiles; TranslationUnits translationUnits; - QTimer sendDiagnosticsTimer; + QTimer sendDocumentAnnotationsTimer; }; } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/translationunit.cpp b/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp index cd880f0567..5df086781f 100644 --- a/src/tools/clangbackend/ipcsource/translationunit.cpp +++ b/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp @@ -28,7 +28,7 @@ ** ****************************************************************************/ -#include "translationunit.h" +#include "clangtranslationunit.h" #include "cursor.h" #include "clangstring.h" @@ -85,6 +85,7 @@ public: uint documentRevision = 0; bool needsToBeReparsed = false; bool hasNewDiagnostics = true; + bool hasNewHighlightingInformations = true; bool isUsedByCurrentEditor = false; bool isVisibleInEditor = false; }; @@ -173,11 +174,18 @@ CXIndex TranslationUnit::index() const CXTranslationUnit TranslationUnit::cxTranslationUnit() const { + cxTranslationUnitWithoutReparsing(); + reparseTranslationUnitIfFilesAreChanged(); + + return d->translationUnit; +} + +CXTranslationUnit TranslationUnit::cxTranslationUnitWithoutReparsing() const +{ checkIfNull(); checkIfFileExists(); removeTranslationUnitIfProjectPartWasChanged(); createTranslationUnitIfNeeded(); - reparseTranslationUnitIfFilesAreChanged(); return d->translationUnit; } @@ -239,6 +247,11 @@ bool TranslationUnit::hasNewDiagnostics() const return d->hasNewDiagnostics; } +bool TranslationUnit::hasNewHighlightingInformations() const +{ + return d->hasNewHighlightingInformations; +} + DiagnosticSet TranslationUnit::diagnostics() const { d->hasNewDiagnostics = false; @@ -268,6 +281,7 @@ void TranslationUnit::setDirtyIfDependencyIsMet(const Utf8String &filePath) if (d->dependedFilePaths.contains(filePath) && isMainFileAndExistsOrIsOtherFile(filePath)) { d->needsToBeReparsed = true; d->hasNewDiagnostics = true; + d->hasNewHighlightingInformations = true; } } @@ -302,6 +316,13 @@ Cursor TranslationUnit::cursor() const return clang_getTranslationUnitCursor(cxTranslationUnit()); } +HighlightingInformations TranslationUnit::highlightingInformations() const +{ + d->hasNewHighlightingInformations = false; + + return highlightingInformationsInRange(cursor().sourceRange()); +} + HighlightingInformations TranslationUnit::highlightingInformationsInRange(const SourceRange &range) const { CXToken *cxTokens = 0; diff --git a/src/tools/clangbackend/ipcsource/translationunit.h b/src/tools/clangbackend/ipcsource/clangtranslationunit.h index 37c4741361..61d58c804c 100644 --- a/src/tools/clangbackend/ipcsource/translationunit.h +++ b/src/tools/clangbackend/ipcsource/clangtranslationunit.h @@ -97,6 +97,7 @@ public: CXIndex index() const; CXTranslationUnit cxTranslationUnit() const; + CXTranslationUnit cxTranslationUnitWithoutReparsing() const; CXUnsavedFile * cxUnsavedFiles() const; uint unsavedFilesCount() const; @@ -112,6 +113,7 @@ public: bool isNeedingReparse() const; bool hasNewDiagnostics() const; + bool hasNewHighlightingInformations() const; DiagnosticSet diagnostics() const; QVector<DiagnosticContainer> mainFileDiagnostics() const; @@ -131,6 +133,7 @@ public: Cursor cursorAt(const Utf8String &filePath, uint line, uint column) const; Cursor cursor() const; + HighlightingInformations highlightingInformations() const; HighlightingInformations highlightingInformationsInRange(const SourceRange &range) const; SkippedSourceRanges skippedSourceRanges() const; diff --git a/src/tools/clangbackend/ipcsource/type.cpp b/src/tools/clangbackend/ipcsource/clangtype.cpp index a1f78e44eb..b839a8dee3 100644 --- a/src/tools/clangbackend/ipcsource/type.cpp +++ b/src/tools/clangbackend/ipcsource/clangtype.cpp @@ -28,7 +28,7 @@ ** ****************************************************************************/ -#include "type.h" +#include "clangtype.h" #include "clangstring.h" #include "cursor.h" diff --git a/src/tools/clangbackend/ipcsource/type.h b/src/tools/clangbackend/ipcsource/clangtype.h index 099bfa4e3e..099bfa4e3e 100644 --- a/src/tools/clangbackend/ipcsource/type.h +++ b/src/tools/clangbackend/ipcsource/clangtype.h diff --git a/src/tools/clangbackend/ipcsource/codecompleter.cpp b/src/tools/clangbackend/ipcsource/codecompleter.cpp index 3f581b5c1c..b628c51eb8 100644 --- a/src/tools/clangbackend/ipcsource/codecompleter.cpp +++ b/src/tools/clangbackend/ipcsource/codecompleter.cpp @@ -34,7 +34,7 @@ #include "clangstring.h" #include "codecompletefailedexception.h" #include "codecompletionsextractor.h" -#include "translationunit.h" +#include "clangtranslationunit.h" #include <clang-c/Index.h> @@ -49,7 +49,7 @@ CodeCompleter::CodeCompleter(TranslationUnit translationUnit) CodeCompletions CodeCompleter::complete(uint line, uint column) { - ClangCodeCompleteResults completeResults(clang_codeCompleteAt(translationUnit.cxTranslationUnit(), + ClangCodeCompleteResults completeResults(clang_codeCompleteAt(translationUnit.cxTranslationUnitWithoutReparsing(), translationUnit.filePath().constData(), line, column, diff --git a/src/tools/clangbackend/ipcsource/codecompleter.h b/src/tools/clangbackend/ipcsource/codecompleter.h index 2d2dc1abe0..971f209c36 100644 --- a/src/tools/clangbackend/ipcsource/codecompleter.h +++ b/src/tools/clangbackend/ipcsource/codecompleter.h @@ -31,7 +31,7 @@ #ifndef CLANGBACKEND_CODECOMPLETER_H #define CLANGBACKEND_CODECOMPLETER_H -#include "translationunit.h" +#include "clangtranslationunit.h" #include <codecompletion.h> diff --git a/src/tools/clangbackend/ipcsource/cursor.h b/src/tools/clangbackend/ipcsource/cursor.h index d4256401e5..4b15e23282 100644 --- a/src/tools/clangbackend/ipcsource/cursor.h +++ b/src/tools/clangbackend/ipcsource/cursor.h @@ -31,7 +31,7 @@ #ifndef CLANGBACKEND_CURSOR_H #define CLANGBACKEND_CURSOR_H -#include "type.h" +#include "clangtype.h" #include <clang-c/Index.h> diff --git a/src/tools/clangbackend/ipcsource/highlightinginformation.cpp b/src/tools/clangbackend/ipcsource/highlightinginformation.cpp index d91ddf26b9..a570f3cf5c 100644 --- a/src/tools/clangbackend/ipcsource/highlightinginformation.cpp +++ b/src/tools/clangbackend/ipcsource/highlightinginformation.cpp @@ -28,6 +28,8 @@ ** ****************************************************************************/ +#include <highlightingmarkcontainer.h> + #include "clangstring.h" #include "cursor.h" #include "highlightinginformation.h" @@ -81,6 +83,11 @@ QVector<HighlightingInformation> HighlightingInformation::outputFunctionArgument return outputFunctionArguments; } +HighlightingInformation::operator HighlightingMarkContainer() const +{ + return HighlightingMarkContainer(line, column, length, type); +} + namespace { bool isFinalFunction(const Cursor &cursor) @@ -278,7 +285,7 @@ HighlightingType HighlightingInformation::kind(CXToken *cxToken, const Cursor &c Q_UNREACHABLE(); } -void PrintTo(const HighlightingInformation& information, ::std::ostream *os) +void PrintTo(const HighlightingInformation &information, ::std::ostream *os) { *os << "type: "; PrintTo(information.type, os); @@ -287,30 +294,4 @@ void PrintTo(const HighlightingInformation& information, ::std::ostream *os) << " length: " << information.length; } -void PrintTo(HighlightingType highlightingType, std::ostream *os) -{ - switch (highlightingType) { - case HighlightingType::Invalid: *os << "Invalid"; break; - case HighlightingType::Comment: *os << "Comment"; break; - case HighlightingType::Keyword: *os << "Keyword"; break; - case HighlightingType::StringLiteral: *os << "StringLiteral"; break; - case HighlightingType::NumberLiteral: *os << "NumberLiteral"; break; - case HighlightingType::Function: *os << "Function"; break; - case HighlightingType::VirtualFunction: *os << "VirtualFunction"; break; - case HighlightingType::Type: *os << "Type"; break; - case HighlightingType::LocalVariable: *os << "LocalVariable"; break; - case HighlightingType::GlobalVariable: *os << "GlobalVariable"; break; - case HighlightingType::Field: *os << "Field"; break; - case HighlightingType::Enumeration: *os << "Enumeration"; break; - case HighlightingType::Operator: *os << "Operator"; break; - case HighlightingType::Preprocessor: *os << "Preprocessor"; break; - case HighlightingType::Label: *os << "Label"; break; - case HighlightingType::OutputArgument: *os << "OutputArgument"; break; - case HighlightingType::PreprocessorDefinition: *os << "PreprocessorDefinition"; break; - case HighlightingType::PreprocessorExpansion: *os << "PreprocessorExpansion"; break; - } -} - - - } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/highlightinginformation.h b/src/tools/clangbackend/ipcsource/highlightinginformation.h index ee327b6213..418efdda8f 100644 --- a/src/tools/clangbackend/ipcsource/highlightinginformation.h +++ b/src/tools/clangbackend/ipcsource/highlightinginformation.h @@ -32,6 +32,7 @@ #define CLANGBACKEND_HIGHLIGHTINGINFORMATION_H #include <clangbackendipc_global.h> +#include <highlightingmarkcontainer.h> #include "cursor.h" @@ -52,6 +53,8 @@ public: bool hasFunctionArguments() const; QVector<HighlightingInformation> outputFunctionArguments() const; + operator HighlightingMarkContainer() const; + private: HighlightingType identifierKind(const Cursor &cursor) const; HighlightingType referencedTypeKind(const Cursor &cursor) const; @@ -71,7 +74,6 @@ private: }; void PrintTo(const HighlightingInformation& highlightingInformation, ::std::ostream *os); -void PrintTo(HighlightingType highlightingType, ::std::ostream *os); inline bool operator==(const HighlightingInformation &first, const HighlightingInformation &second) { diff --git a/src/tools/clangbackend/ipcsource/highlightinginformations.cpp b/src/tools/clangbackend/ipcsource/highlightinginformations.cpp index f7157768fd..c90ea4a590 100644 --- a/src/tools/clangbackend/ipcsource/highlightinginformations.cpp +++ b/src/tools/clangbackend/ipcsource/highlightinginformations.cpp @@ -30,6 +30,10 @@ #include "highlightinginformations.h" +#include "highlightingmarkcontainer.h" + +#include <QVector> + namespace ClangBackEnd { HighlightingInformations::HighlightingInformations(CXTranslationUnit cxTranslationUnit, CXToken *tokens, uint tokensCount) @@ -56,6 +60,20 @@ HighlightingInformations::const_iterator HighlightingInformations::end() const return const_iterator(cxCursor.cend(), cxToken + cxTokenCount, cxTranslationUnit); } +QVector<HighlightingMarkContainer> HighlightingInformations::toHighlightingMarksContainers() const +{ + QVector<HighlightingMarkContainer> containers; + containers.reserve(size()); + + const auto isValidHighlightMark = [] (const HighlightingInformation &highlightMark) { + return !highlightMark.hasType(HighlightingType::Invalid); + }; + + std::copy_if(begin(), end(), std::back_inserter(containers), isValidHighlightMark); + + return containers; +} + bool HighlightingInformations::isEmpty() const { return cxTokenCount == 0; diff --git a/src/tools/clangbackend/ipcsource/highlightinginformations.h b/src/tools/clangbackend/ipcsource/highlightinginformations.h index 2c7b8ce9bb..7b3365780e 100644 --- a/src/tools/clangbackend/ipcsource/highlightinginformations.h +++ b/src/tools/clangbackend/ipcsource/highlightinginformations.h @@ -40,6 +40,7 @@ namespace ClangBackEnd { using uint = unsigned int; +class HighlightingMarkContainer; class HighlightingInformations { @@ -61,6 +62,8 @@ public: const_iterator begin() const; const_iterator end() const; + QVector<HighlightingMarkContainer> toHighlightingMarksContainers() const; + private: CXTranslationUnit cxTranslationUnit = nullptr; CXToken *const cxToken = nullptr; diff --git a/src/tools/clangbackend/ipcsource/highlightinginformationsiterator.h b/src/tools/clangbackend/ipcsource/highlightinginformationsiterator.h index 53f540970e..ae868569bf 100644 --- a/src/tools/clangbackend/ipcsource/highlightinginformationsiterator.h +++ b/src/tools/clangbackend/ipcsource/highlightinginformationsiterator.h @@ -56,10 +56,6 @@ public: cxTranslationUnit(cxTranslationUnit) {} - HighlightingInformationsIterator(const HighlightingInformationsIterator &other) - : cxCursorIterator(other.cxCursorIterator) - {} - HighlightingInformationsIterator& operator++() { ++cxCursorIterator; diff --git a/src/tools/clangbackend/ipcsource/sourcelocation.cpp b/src/tools/clangbackend/ipcsource/sourcelocation.cpp index e04f44c7d8..92c5464d7f 100644 --- a/src/tools/clangbackend/ipcsource/sourcelocation.cpp +++ b/src/tools/clangbackend/ipcsource/sourcelocation.cpp @@ -31,7 +31,7 @@ #include "sourcelocation.h" #include "clangstring.h" -#include "translationunit.h" +#include "clangtranslationunit.h" #include <utf8string.h> diff --git a/src/tools/clangbackend/ipcsource/translationunits.cpp b/src/tools/clangbackend/ipcsource/translationunits.cpp index 07975bf693..885eabaefa 100644 --- a/src/tools/clangbackend/ipcsource/translationunits.cpp +++ b/src/tools/clangbackend/ipcsource/translationunits.cpp @@ -32,8 +32,11 @@ #include <diagnosticschangedmessage.h> #include <diagnosticset.h> +#include <highlightingchangedmessage.h> +#include <highlightinginformations.h> #include <projectpartsdonotexistexception.h> #include <projects.h> +#include <skippedsourceranges.h> #include <translationunitalreadyexistsexception.h> #include <translationunitdoesnotexistexception.h> @@ -60,12 +63,16 @@ TranslationUnits::TranslationUnits(ProjectParts &projects, UnsavedFiles &unsaved { } -void TranslationUnits::create(const QVector<FileContainer> &fileContainers) +std::vector<TranslationUnit> TranslationUnits::create(const QVector<FileContainer> &fileContainers) { checkIfTranslationUnitsDoesNotExists(fileContainers); + std::vector<TranslationUnit> createdTranslationUnits; + for (const FileContainer &fileContainer : fileContainers) - createTranslationUnit(fileContainer); + createdTranslationUnits.push_back(createTranslationUnit(fileContainer)); + + return createdTranslationUnits; } void TranslationUnits::update(const QVector<FileContainer> &fileContainers) @@ -97,13 +104,13 @@ void TranslationUnits::remove(const QVector<FileContainer> &fileContainers) updateTranslationUnitsWithChangedDependencies(fileContainers); } -void TranslationUnits::setCurrentEditor(const Utf8String &filePath) +void TranslationUnits::setUsedByCurrentEditor(const Utf8String &filePath) { for (TranslationUnit &translationUnit : translationUnits_) translationUnit.setIsUsedByCurrentEditor(translationUnit.filePath() == filePath); } -void TranslationUnits::setVisibleEditors(const Utf8StringVector &filePaths) +void TranslationUnits::setVisibleInEditors(const Utf8StringVector &filePaths) { for (TranslationUnit &translationUnit : translationUnits_) translationUnit.setIsVisibleInEditor(filePaths.contains(translationUnit.filePath())); @@ -163,62 +170,71 @@ void TranslationUnits::updateTranslationUnitsWithChangedDependencies(const QVect updateTranslationUnitsWithChangedDependency(fileContainer.filePath()); } -DiagnosticSendState TranslationUnits::sendChangedDiagnostics() +DocumentAnnotationsSendState TranslationUnits::sendDocumentAnnotations() { - auto diagnosticSendState = sendChangedDiagnosticsForCurrentEditor(); - if (diagnosticSendState == DiagnosticSendState::NoDiagnosticSend) - diagnosticSendState = sendChangedDiagnosticsForVisibleEditors(); - if (diagnosticSendState == DiagnosticSendState::NoDiagnosticSend) - diagnosticSendState = sendChangedDiagnosticsForAll(); + auto documentAnnotationsSendState = sendDocumentAnnotationsForCurrentEditor(); + if (documentAnnotationsSendState == DocumentAnnotationsSendState::NoDocumentAnnotationsSent) + documentAnnotationsSendState = sendDocumentAnnotationsForVisibleEditors(); - return diagnosticSendState; + return documentAnnotationsSendState; } template<class Predicate> -DiagnosticSendState TranslationUnits::sendChangedDiagnostics(Predicate predicate) +DocumentAnnotationsSendState TranslationUnits::sendDocumentAnnotations(Predicate predicate) { auto foundTranslationUnit = std::find_if(translationUnits_.begin(), translationUnits_.end(), predicate); if (foundTranslationUnit != translationUnits().end()) { - sendDiagnosticChangedMessage(*foundTranslationUnit); - return DiagnosticSendState::MaybeThereAreMoreDiagnostics; + sendDocumentAnnotations(*foundTranslationUnit); + return DocumentAnnotationsSendState::MaybeThereAreDocumentAnnotations; } - return DiagnosticSendState::NoDiagnosticSend; + return DocumentAnnotationsSendState::NoDocumentAnnotationsSent; +} + +namespace { + +bool translationUnitHasNewDocumentAnnotations(const TranslationUnit &translationUnit) +{ + return translationUnit.hasNewDiagnostics() || translationUnit.hasNewHighlightingInformations(); +} + } -DiagnosticSendState TranslationUnits::sendChangedDiagnosticsForCurrentEditor() +DocumentAnnotationsSendState TranslationUnits::sendDocumentAnnotationsForCurrentEditor() { - auto hasDiagnosticsForCurrentEditor = [] (const TranslationUnit &translationUnit) { - return translationUnit.isUsedByCurrentEditor() && translationUnit.hasNewDiagnostics(); + auto hasDocumentAnnotationsForCurrentEditor = [] (const TranslationUnit &translationUnit) { + return translationUnit.isUsedByCurrentEditor() + && translationUnitHasNewDocumentAnnotations(translationUnit); }; - return sendChangedDiagnostics(hasDiagnosticsForCurrentEditor); + return sendDocumentAnnotations(hasDocumentAnnotationsForCurrentEditor); } -DiagnosticSendState TranslationUnits::sendChangedDiagnosticsForVisibleEditors() +DocumentAnnotationsSendState TranslationUnits::sendDocumentAnnotationsForVisibleEditors() { - auto hasDiagnosticsForVisibleEditor = [] (const TranslationUnit &translationUnit) { - return translationUnit.isVisibleInEditor() && translationUnit.hasNewDiagnostics(); + auto hasDocumentAnnotationsForVisibleEditor = [] (const TranslationUnit &translationUnit) { + return translationUnit.isVisibleInEditor() + && translationUnitHasNewDocumentAnnotations(translationUnit); }; - return sendChangedDiagnostics(hasDiagnosticsForVisibleEditor); + return sendDocumentAnnotations(hasDocumentAnnotationsForVisibleEditor); } -DiagnosticSendState TranslationUnits::sendChangedDiagnosticsForAll() +DocumentAnnotationsSendState TranslationUnits::sendDocumentAnnotationsForAll() { - auto hasDiagnostics = [] (const TranslationUnit &translationUnit) { - return translationUnit.hasNewDiagnostics(); + auto hasDocumentAnnotations = [] (const TranslationUnit &translationUnit) { + return translationUnitHasNewDocumentAnnotations(translationUnit); }; - return sendChangedDiagnostics(hasDiagnostics); + return sendDocumentAnnotations(hasDocumentAnnotations); } -void TranslationUnits::setSendChangeDiagnosticsCallback(std::function<void(const DiagnosticsChangedMessage &)> &&callback) +void TranslationUnits::setSendDocumentAnnotationsCallback(SendDocumentAnnotationsCallback &&callback) { - sendDiagnosticsChangedCallback = std::move(callback); + sendDocumentAnnotationsCallback = std::move(callback); } QVector<FileContainer> TranslationUnits::newerFileContainers(const QVector<FileContainer> &fileContainers) const @@ -246,18 +262,19 @@ const ClangFileSystemWatcher *TranslationUnits::clangFileSystemWatcher() const return &fileSystemWatcher; } -void TranslationUnits::createTranslationUnit(const FileContainer &fileContainer) +TranslationUnit TranslationUnits::createTranslationUnit(const FileContainer &fileContainer) { TranslationUnit::FileExistsCheck checkIfFileExists = fileContainer.hasUnsavedFileContent() ? TranslationUnit::DoNotCheckIfFileExists : TranslationUnit::CheckIfFileExists; - auto findIterator = findTranslationUnit(fileContainer); - if (findIterator == translationUnits_.end()) { - translationUnits_.push_back(TranslationUnit(fileContainer.filePath(), - projectParts.project(fileContainer.projectPartId()), - fileContainer.fileArguments(), - *this, - checkIfFileExists)); - translationUnits_.back().setDocumentRevision(fileContainer.documentRevision()); - } + + translationUnits_.emplace_back(fileContainer.filePath(), + projectParts.project(fileContainer.projectPartId()), + fileContainer.fileArguments(), + *this, + checkIfFileExists); + + translationUnits_.back().setDocumentRevision(fileContainer.documentRevision()); + + return translationUnits_.back(); } void TranslationUnits::updateTranslationUnit(const FileContainer &fileContainer) @@ -340,13 +357,18 @@ void TranslationUnits::checkIfTranslationUnitsForFilePathsDoesExists(const QVect } } -void TranslationUnits::sendDiagnosticChangedMessage(const TranslationUnit &translationUnit) +void TranslationUnits::sendDocumentAnnotations(const TranslationUnit &translationUnit) { - if (sendDiagnosticsChangedCallback) { - DiagnosticsChangedMessage message(translationUnit.fileContainer(), - translationUnit.mainFileDiagnostics()); + if (sendDocumentAnnotationsCallback) { + const auto fileContainer = translationUnit.fileContainer(); + DiagnosticsChangedMessage diagnosticsMessage(fileContainer, + translationUnit.mainFileDiagnostics()); + HighlightingChangedMessage highlightingsMessage(fileContainer, + translationUnit.highlightingInformations().toHighlightingMarksContainers(), + translationUnit.skippedSourceRanges().toSourceRangeContainers()); - sendDiagnosticsChangedCallback(std::move(message)); + sendDocumentAnnotationsCallback(std::move(diagnosticsMessage), + std::move(highlightingsMessage)); } } diff --git a/src/tools/clangbackend/ipcsource/translationunits.h b/src/tools/clangbackend/ipcsource/translationunits.h index a08d642d48..49ed36e7e2 100644 --- a/src/tools/clangbackend/ipcsource/translationunits.h +++ b/src/tools/clangbackend/ipcsource/translationunits.h @@ -32,7 +32,7 @@ #define CLANGBACKEND_TRANSLATIONUNITS_H #include "clangfilesystemwatcher.h" -#include "translationunit.h" +#include "clangtranslationunit.h" #include <filecontainer.h> @@ -46,24 +46,30 @@ namespace ClangBackEnd { class ProjectParts; class UnsavedFiles; class DiagnosticsChangedMessage; +class HighlightingChangedMessage; -enum class DiagnosticSendState +enum class DocumentAnnotationsSendState { - NoDiagnosticSend, - MaybeThereAreMoreDiagnostics, + NoDocumentAnnotationsSent, + MaybeThereAreDocumentAnnotations, }; class TranslationUnits { public: + using SendDocumentAnnotationsCallback + = std::function<void (const DiagnosticsChangedMessage &, + const HighlightingChangedMessage &)>; + +public: TranslationUnits(ProjectParts &projectParts, UnsavedFiles &unsavedFiles); - void create(const QVector<FileContainer> &fileContainers); + std::vector<TranslationUnit> create(const QVector<FileContainer> &fileContainers); void update(const QVector<FileContainer> &fileContainers); void remove(const QVector<FileContainer> &fileContainers); - void setCurrentEditor(const Utf8String &filePath); - void setVisibleEditors(const Utf8StringVector &filePaths); + void setUsedByCurrentEditor(const Utf8String &filePath); + void setVisibleInEditors(const Utf8StringVector &filePaths); const TranslationUnit &translationUnit(const Utf8String &filePath, const Utf8String &projectPartId) const; const TranslationUnit &translationUnit(const FileContainer &fileContainer) const; @@ -78,19 +84,19 @@ public: void updateTranslationUnitsWithChangedDependency(const Utf8String &filePath); void updateTranslationUnitsWithChangedDependencies(const QVector<FileContainer> &fileContainers); - DiagnosticSendState sendChangedDiagnostics(); - DiagnosticSendState sendChangedDiagnosticsForCurrentEditor(); - DiagnosticSendState sendChangedDiagnosticsForVisibleEditors(); - DiagnosticSendState sendChangedDiagnosticsForAll(); + DocumentAnnotationsSendState sendDocumentAnnotationsForCurrentEditor(); + DocumentAnnotationsSendState sendDocumentAnnotationsForVisibleEditors(); + DocumentAnnotationsSendState sendDocumentAnnotationsForAll(); + DocumentAnnotationsSendState sendDocumentAnnotations(); - void setSendChangeDiagnosticsCallback(std::function<void(const DiagnosticsChangedMessage&)> &&callback); + void setSendDocumentAnnotationsCallback(SendDocumentAnnotationsCallback &&callback); QVector<FileContainer> newerFileContainers(const QVector<FileContainer> &fileContainers) const; const ClangFileSystemWatcher *clangFileSystemWatcher() const; private: - void createTranslationUnit(const FileContainer &fileContainer); + TranslationUnit createTranslationUnit(const FileContainer &fileContainer); void updateTranslationUnit(const FileContainer &fileContainer); std::vector<TranslationUnit>::iterator findTranslationUnit(const FileContainer &fileContainer); std::vector<TranslationUnit>::iterator findAllTranslationUnitWithFilePath(const Utf8String &filePath); @@ -102,15 +108,15 @@ private: void checkIfTranslationUnitsDoesNotExists(const QVector<FileContainer> &fileContainers) const; void checkIfTranslationUnitsForFilePathsDoesExists(const QVector<FileContainer> &fileContainers) const; - void sendDiagnosticChangedMessage(const TranslationUnit &translationUnit); void removeTranslationUnits(const QVector<FileContainer> &fileContainers); template<class Predicate> - DiagnosticSendState sendChangedDiagnostics(Predicate predicate); + DocumentAnnotationsSendState sendDocumentAnnotations(Predicate predicate); + void sendDocumentAnnotations(const TranslationUnit &translationUnit); private: ClangFileSystemWatcher fileSystemWatcher; - std::function<void(const DiagnosticsChangedMessage&)> sendDiagnosticsChangedCallback; + SendDocumentAnnotationsCallback sendDocumentAnnotationsCallback; std::vector<TranslationUnit> translationUnits_; ProjectParts &projectParts; UnsavedFiles &unsavedFiles_; |