diff options
Diffstat (limited to 'src/libs/clangsupport')
23 files changed, 697 insertions, 96 deletions
diff --git a/src/libs/clangsupport/CMakeLists.txt b/src/libs/clangsupport/CMakeLists.txt new file mode 100644 index 0000000000..84cdbaf8b9 --- /dev/null +++ b/src/libs/clangsupport/CMakeLists.txt @@ -0,0 +1,137 @@ +add_qtc_library(ClangSupport + PUBLIC_DEPENDS Utils Sqlite Qt5::Core Qt5::Network + PUBLIC_INCLUDES "${CMAKE_CURRENT_LIST_DIR}" + PUBLIC_DEFINES + CLANG_VERSION="${CLANG_VERSION}" + CLANG_RESOURCE_DIR="${CLANG_RESOURCE_DIR}" + CLANG_BINDIR="${CLANG_BIN_DIR}" + DEFINES CLANGSUPPORT_BUILD_LIB + SOURCES + alivemessage.cpp alivemessage.h + annotationsmessage.cpp annotationsmessage.h + baseserverproxy.cpp baseserverproxy.h + cancelmessage.cpp cancelmessage.h + changedfilepathcompressor.h + clangcodemodelclientinterface.cpp clangcodemodelclientinterface.h + clangcodemodelclientmessages.h + clangcodemodelclientproxy.cpp clangcodemodelclientproxy.h + clangcodemodelconnectionclient.cpp clangcodemodelconnectionclient.h + clangcodemodelserverinterface.cpp clangcodemodelserverinterface.h + clangcodemodelservermessages.h + clangcodemodelserverproxy.cpp clangcodemodelserverproxy.h + clangpathwatcher.h + clangpathwatcherinterface.h + clangpathwatchernotifier.h + clangrefactoringclientmessages.h + clangrefactoringmessages.h + clangrefactoringservermessages.h + clangsupport_global.h + clangsupportdebugutils.cpp clangsupportdebugutils.h + clangsupportexceptions.h + codecompletion.cpp codecompletion.h + codecompletionchunk.cpp codecompletionchunk.h + commandlinebuilder.h + compilermacro.h + completionsmessage.cpp completionsmessage.h + connectionclient.cpp connectionclient.h + connectionserver.cpp connectionserver.h + diagnosticcontainer.cpp diagnosticcontainer.h + documentschangedmessage.cpp documentschangedmessage.h + documentsclosedmessage.cpp documentsclosedmessage.h + documentsopenedmessage.cpp documentsopenedmessage.h + documentvisibilitychangedmessage.cpp documentvisibilitychangedmessage.h + dynamicastmatcherdiagnosticcontainer.cpp dynamicastmatcherdiagnosticcontainer.h + dynamicastmatcherdiagnosticcontextcontainer.cpp dynamicastmatcherdiagnosticcontextcontainer.h + dynamicastmatcherdiagnosticmessagecontainer.cpp dynamicastmatcherdiagnosticmessagecontainer.h + dynamicmatcherdiagnostics.h + echomessage.cpp echomessage.h + endmessage.cpp endmessage.h + environment.h + executeinloop.h + filecontainer.cpp filecontainer.h + filecontainerv2.cpp filecontainerv2.h + filepath.cpp filepath.h + filepathcache.h + filepathcaching.cpp filepathcaching.h + filepathcachingfwd.h + filepathcachinginterface.h + filepathexceptions.h + filepathid.cpp filepathid.h + filepathstorage.h + filepathstoragesources.h + filepathstoragesqlitestatementfactory.h + filepathview.h + fixitcontainer.cpp fixitcontainer.h + followsymbolmessage.cpp followsymbolmessage.h + generatedfiles.cpp generatedfiles.h + generatedfilesinterface.h + idpaths.h + includesearchpath.h + ipcclientinterface.h + ipcclientprovider.h + ipcinterface.h + ipcserverinterface.h + lineprefixer.cpp lineprefixer.h + messageenvelop.cpp messageenvelop.h + modifiedtimechecker.h + modifiedtimecheckerinterface.h + nativefilepath.h + pchmanagerclientinterface.cpp pchmanagerclientinterface.h + pchmanagerclientproxy.cpp pchmanagerclientproxy.h + pchmanagerserverinterface.cpp pchmanagerserverinterface.h + pchmanagerserverproxy.cpp pchmanagerserverproxy.h + pchpaths.h + precompiledheadersupdatedmessage.cpp precompiledheadersupdatedmessage.h + processcreator.cpp processcreator.h + processexception.cpp processexception.h + processhandle.h + processstartedevent.cpp processstartedevent.h + progresscounter.h + progressmessage.h + projectmanagementserverinterface.h + projectpartartefact.cpp projectpartartefact.h + projectpartcontainer.cpp projectpartcontainer.h + projectpartid.h + projectpartpch.cpp projectpartpch.h + projectpartsstorage.h + projectpartsstorageinterface.h + readmessageblock.cpp readmessageblock.h + refactoringclientinterface.cpp refactoringclientinterface.h + refactoringclientproxy.cpp refactoringclientproxy.h + refactoringdatabaseinitializer.h + refactoringserverinterface.cpp refactoringserverinterface.h + refactoringserverproxy.cpp refactoringserverproxy.h + referencesmessage.cpp referencesmessage.h + removegeneratedfilesmessage.cpp removegeneratedfilesmessage.h + removeprojectpartsmessage.h + requestannotationsmessage.cpp requestannotationsmessage.h + requestcompletionsmessage.cpp requestcompletionsmessage.h + requestfollowsymbolmessage.cpp requestfollowsymbolmessage.h + requestreferencesmessage.cpp requestreferencesmessage.h + requestsourcelocationforrenamingmessage.cpp requestsourcelocationforrenamingmessage.h + requestsourcerangesanddiagnosticsforquerymessage.cpp requestsourcerangesanddiagnosticsforquerymessage.h + requestsourcerangesforquerymessage.cpp requestsourcerangesforquerymessage.h + requesttooltipmessage.cpp requesttooltipmessage.h + sourceentry.h + sourcelocationcontainer.cpp sourcelocationcontainer.h + sourcelocationcontainerv2.cpp sourcelocationcontainerv2.h + sourcelocationscontainer.cpp sourcelocationscontainer.h + sourcelocationsforrenamingmessage.cpp sourcelocationsforrenamingmessage.h + sourcerangecontainer.cpp sourcerangecontainer.h + sourcerangecontainerv2.cpp sourcerangecontainerv2.h + sourcerangesanddiagnosticsforquerymessage.cpp sourcerangesanddiagnosticsforquerymessage.h + sourcerangescontainer.cpp sourcerangescontainer.h + sourcerangesforquerymessage.cpp sourcerangesforquerymessage.h + sourcerangewithtextcontainer.cpp sourcerangewithtextcontainer.h + stringcache.h + stringcachealgorithms.h + stringcachefwd.h + tokeninfocontainer.cpp tokeninfocontainer.h + tooltipinfo.cpp tooltipinfo.h + tooltipmessage.cpp tooltipmessage.h + unsavedfilesremovedmessage.cpp unsavedfilesremovedmessage.h + unsavedfilesupdatedmessage.cpp unsavedfilesupdatedmessage.h + updategeneratedfilesmessage.cpp updategeneratedfilesmessage.h + updateprojectpartsmessage.cpp updateprojectpartsmessage.h + writemessageblock.cpp writemessageblock.h +) diff --git a/src/libs/clangsupport/clangsupport-lib.pri b/src/libs/clangsupport/clangsupport-lib.pri index 0668382803..df537f5848 100644 --- a/src/libs/clangsupport/clangsupport-lib.pri +++ b/src/libs/clangsupport/clangsupport-lib.pri @@ -110,6 +110,7 @@ HEADERS += \ $$PWD/clangsupportexceptions.h \ $$PWD/completionsmessage.h \ $$PWD/executeinloop.h \ + $$PWD/pchpaths.h \ $$PWD/projectpartid.h \ $$PWD/projectpartsstorage.h \ $$PWD/projectpartsstorageinterface.h \ @@ -203,7 +204,6 @@ HEADERS += \ $$PWD/nativefilepath.h \ $$PWD/filepathview.h \ $$PWD/compilermacro.h \ - $$PWD/projectpartpchproviderinterface.h \ $$PWD/updategeneratedfilesmessage.h \ $$PWD/removegeneratedfilesmessage.h \ $$PWD/generatedfiles.h \ @@ -213,6 +213,10 @@ HEADERS += \ $$PWD/includesearchpath.h \ $$PWD/commandlinebuilder.h \ $$PWD/projectpartartefact.h \ - $$PWD/projectpartcontainer.h + $$PWD/projectpartcontainer.h \ + $$PWD/sourceentry.h \ + $$PWD/modifiedtimecheckerinterface.h \ + $$PWD/environment.h \ + $$PWD/modifiedtimechecker.h contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols diff --git a/src/libs/clangsupport/commandlinebuilder.h b/src/libs/clangsupport/commandlinebuilder.h index 9de1da68d3..dedcf1c518 100644 --- a/src/libs/clangsupport/commandlinebuilder.h +++ b/src/libs/clangsupport/commandlinebuilder.h @@ -33,6 +33,9 @@ #include <utils/smallstringvector.h> #include <utils/cpplanguage_details.h> +#include <QCoreApplication> +#include <QDir> + namespace ClangBackEnd { enum class InputFileType : unsigned char { Header, Source }; @@ -46,7 +49,8 @@ public: InputFileType sourceType = InputFileType::Header, FilePathView sourcePath = {}, FilePathView outputPath = {}, - FilePathView includePchPath = {}) + FilePathView includePchPath = {}, + NativeFilePathView preIncludeSearchPath = {}) { commandLine.reserve(1024); @@ -58,6 +62,7 @@ public: addLanguageVersion(projectInfo); addNoStdIncAndNoStdLibInc(projectInfo.language); addCompilerMacros(projectInfo.compilerMacros); + addPreIncludeSearchPath(preIncludeSearchPath); addProjectIncludeSearchPaths( sortedIncludeSearchPaths(projectInfo.projectIncludeSearchPaths)); addSystemAndBuiltInIncludeSearchPaths( @@ -97,9 +102,12 @@ public: if (projectInfo.languageExtension && Utils::LanguageExtension::ObjectiveC) return sourceType == InputFileType::Header ? "objective-c++-header" : "objective-c++"; + return sourceType == InputFileType::Header ? "c++-header" : "c++"; + case Utils::Language::None: + return "none"; } - return sourceType == InputFileType::Header ? "c++-header" : "c++"; + return "none"; } void addLanguage(const ProjectInfo &projectInfo, InputFileType sourceType) @@ -131,6 +139,8 @@ public: return "-std=c++17"; case Utils::LanguageVersion::CXX2a: return "-std=c++2a"; + case Utils::LanguageVersion::None: + return ""; } return "-std=c++2a"; @@ -159,6 +169,8 @@ public: return "-std=gnu++17"; case Utils::LanguageVersion::CXX2a: return "-std=gnu++2a"; + case Utils::LanguageVersion::None: + return ""; } return "-std=gnu++2a"; @@ -209,6 +221,14 @@ public: commandLine.emplace_back(Utils::SmallString{"-D", macro.key, "=", macro.value}); } + void addPreIncludeSearchPath(NativeFilePathView preIncludeSearchPath) + { + if (!preIncludeSearchPath.empty()) { + commandLine.emplace_back("-isystem"); + commandLine.emplace_back(preIncludeSearchPath); + } + } + IncludeSearchPaths sortedIncludeSearchPaths(const IncludeSearchPaths &unsortedPaths) { IncludeSearchPaths paths = unsortedPaths; diff --git a/src/libs/clangsupport/connectionclient.cpp b/src/libs/clangsupport/connectionclient.cpp index bdbedab5c0..b3025baeea 100644 --- a/src/libs/clangsupport/connectionclient.cpp +++ b/src/libs/clangsupport/connectionclient.cpp @@ -325,7 +325,7 @@ void ConnectionClient::connectStandardOutputAndError(QProcess *process) const void ConnectionClient::connectLocalSocketError() const { connect(m_localSocket, - static_cast<void (QLocalSocket::*)(QLocalSocket::LocalSocketError)>(&QLocalSocket::error), + QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error), this, &ConnectionClient::printLocalSocketError); } diff --git a/src/libs/clangsupport/connectionserver.h b/src/libs/clangsupport/connectionserver.h index 8f13e631c5..b60083c4f8 100644 --- a/src/libs/clangsupport/connectionserver.h +++ b/src/libs/clangsupport/connectionserver.h @@ -72,11 +72,17 @@ public: } + void ensureAliveMessageIsSent() + { + if (m_aliveTimer.remainingTime() == 0) + sendAliveMessage(); + } + private: void connectToLocalServer(const QString &connectionName) { QObject::connect(&m_localSocket, - static_cast<void (QLocalSocket::*)(QLocalSocket::LocalSocketError)>(&QLocalSocket::error), + QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error), [&] (QLocalSocket::LocalSocketError) { qWarning() << "ConnectionServer error:" << m_localSocket.errorString() << connectionName; }); diff --git a/src/libs/clangsupport/ipcserverinterface.cpp b/src/libs/clangsupport/environment.h index fbc92de52e..ffa4d907cc 100644 --- a/src/libs/clangsupport/ipcserverinterface.cpp +++ b/src/libs/clangsupport/environment.h @@ -23,9 +23,25 @@ ** ****************************************************************************/ -#include "ipcserverinterface.h" +#pragma once + +#include <nativefilepath.h> namespace ClangBackEnd { +class Environment +{ +public: + Environment() = default; + Environment(const Environment &) = delete; + Environment &operator=(const Environment &) = delete; + + virtual Utils::PathString pchBuildDirectory() const = 0; + virtual uint hardwareConcurrency() const = 0; + virtual NativeFilePathView preIncludeSearchPath() const = 0; + +protected: + ~Environment() = default; +}; } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/executeinloop.h b/src/libs/clangsupport/executeinloop.h index 9c3eddeb4d..3642c3ccd3 100644 --- a/src/libs/clangsupport/executeinloop.h +++ b/src/libs/clangsupport/executeinloop.h @@ -29,38 +29,6 @@ #include <QCoreApplication> #include <QThread> -#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) -template<typename CallableType> -class CallableEvent : public QEvent -{ -public: - using Callable = std::decay_t<CallableType>; - CallableEvent(Callable &&callable) - : QEvent(QEvent::None) - , callable(std::move(callable)) - {} - CallableEvent(const Callable &callable) - : QEvent(QEvent::None) - , callable(callable) - {} - - ~CallableEvent() { callable(); } - -public: - Callable callable; -}; - -template<typename Callable> -void executeInLoop(Callable &&callable, QObject *object = QCoreApplication::instance()) -{ - if (QThread *thread = qobject_cast<QThread *>(object)) - object = QAbstractEventDispatcher::instance(thread); - - QCoreApplication::postEvent(object, - new CallableEvent<Callable>(std::forward<Callable>(callable)), - Qt::HighEventPriority); -} -#else template<typename Callable> void executeInLoop(Callable &&callable, QObject *object = QCoreApplication::instance()) { @@ -69,4 +37,3 @@ void executeInLoop(Callable &&callable, QObject *object = QCoreApplication::inst QMetaObject::invokeMethod(object, std::forward<Callable>(callable)); } -#endif diff --git a/src/libs/clangsupport/generatedfiles.cpp b/src/libs/clangsupport/generatedfiles.cpp index f4863baba5..644137886b 100644 --- a/src/libs/clangsupport/generatedfiles.cpp +++ b/src/libs/clangsupport/generatedfiles.cpp @@ -25,6 +25,8 @@ #include "generatedfiles.h" +#include <utils/algorithm.h> + namespace ClangBackEnd { void GeneratedFiles::update(V2::FileContainers &&fileContainers) @@ -32,16 +34,16 @@ void GeneratedFiles::update(V2::FileContainers &&fileContainers) V2::FileContainers unionFileContainers; unionFileContainers.reserve(m_fileContainers.size() + fileContainers.size()); - auto compare = [] (const V2::FileContainer &first, const V2::FileContainer &second) { + auto compare = [](const V2::FileContainer &first, const V2::FileContainer &second) { return first.filePath < second.filePath; }; - std::set_union(std::make_move_iterator(fileContainers.begin()), - std::make_move_iterator(fileContainers.end()), - std::make_move_iterator(m_fileContainers.begin()), - std::make_move_iterator(m_fileContainers.end()), - std::back_inserter(unionFileContainers), - compare); + Utils::set_union(std::make_move_iterator(fileContainers.begin()), + std::make_move_iterator(fileContainers.end()), + std::make_move_iterator(m_fileContainers.begin()), + std::make_move_iterator(m_fileContainers.end()), + std::back_inserter(unionFileContainers), + compare); m_fileContainers = std::move(unionFileContainers); } @@ -55,12 +57,12 @@ void GeneratedFiles::update(const V2::FileContainers &fileContainers) return first.filePath < second.filePath; }; - std::set_union(fileContainers.begin(), - fileContainers.end(), - std::make_move_iterator(m_fileContainers.begin()), - std::make_move_iterator(m_fileContainers.end()), - std::back_inserter(unionFileContainers), - compare); + Utils::set_union(fileContainers.begin(), + fileContainers.end(), + std::make_move_iterator(m_fileContainers.begin()), + std::make_move_iterator(m_fileContainers.end()), + std::back_inserter(unionFileContainers), + compare); m_fileContainers = std::move(unionFileContainers); } diff --git a/src/libs/clangsupport/modifiedtimechecker.h b/src/libs/clangsupport/modifiedtimechecker.h new file mode 100644 index 0000000000..c9b62c4673 --- /dev/null +++ b/src/libs/clangsupport/modifiedtimechecker.h @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "filepathcachinginterface.h" +#include "modifiedtimecheckerinterface.h" + +#include <algorithm> +#include <iterator> + +namespace ClangBackEnd { +template<typename SourceEntries = ::ClangBackEnd::SourceEntries> +class ModifiedTimeChecker final : public ModifiedTimeCheckerInterface<SourceEntries> +{ + using SourceEntry = typename SourceEntries::value_type; + +public: + using GetModifiedTime = std::function<ClangBackEnd::TimeStamp(ClangBackEnd::FilePathView filePath)>; + ModifiedTimeChecker(GetModifiedTime &getModifiedTime, FilePathCachingInterface &filePathCache) + : m_getModifiedTime(getModifiedTime) + , m_filePathCache(filePathCache) + {} + + bool isUpToDate(const SourceEntries &sourceEntries) const + { + if (sourceEntries.empty()) + return false; + + updateCurrentSourceTimeStamps(sourceEntries); + + return compareEntries(sourceEntries); + } + + void pathsChanged(const FilePathIds &filePathIds) + { + using SourceTimeStampReferences = std::vector<std::reference_wrapper<SourceTimeStamp>>; + + SourceTimeStampReferences timeStampsToUpdate; + timeStampsToUpdate.reserve(filePathIds.size()); + + std::set_intersection(m_currentSourceTimeStamps.begin(), + m_currentSourceTimeStamps.end(), + filePathIds.begin(), + filePathIds.end(), + std::back_inserter(timeStampsToUpdate)); + + for (SourceTimeStamp &sourceTimeStamp : timeStampsToUpdate) { + sourceTimeStamp.timeStamp = m_getModifiedTime( + m_filePathCache.filePath(sourceTimeStamp.sourceId)); + } + } + +private: + bool compareEntries(const SourceEntries &sourceEntries) const + { + class CompareSourceId + { + public: + bool operator()(SourceTimeStamp first, SourceTimeStamp second) + { + return first.sourceId < second.sourceId; + } + + bool operator()(::ClangBackEnd::SourceEntry first, ::ClangBackEnd::SourceEntry second) + { + return first.sourceId < second.sourceId; + } + + bool operator()(SourceTimeStamp first, ::ClangBackEnd::SourceEntry second) + { + return first.sourceId < second.sourceId; + } + + bool operator()(::ClangBackEnd::SourceEntry first, SourceTimeStamp second) + { + return first.sourceId < second.sourceId; + } + }; + + SourceTimeStamps currentSourceTimeStamp; + currentSourceTimeStamp.reserve(sourceEntries.size()); + std::set_intersection(m_currentSourceTimeStamps.begin(), + m_currentSourceTimeStamps.end(), + sourceEntries.begin(), + sourceEntries.end(), + std::back_inserter(currentSourceTimeStamp), + CompareSourceId{}); + + class CompareTime + { + public: + bool operator()(SourceTimeStamp first, SourceTimeStamp second) + { + return first.timeStamp <= second.timeStamp; + } + + bool operator()(::ClangBackEnd::SourceEntry first, ::ClangBackEnd::SourceEntry second) + { + return first.timeStamp <= second.timeStamp; + } + + bool operator()(SourceTimeStamp first, ::ClangBackEnd::SourceEntry second) + { + return first.timeStamp <= second.timeStamp; + } + + bool operator()(::ClangBackEnd::SourceEntry first, SourceTimeStamp second) + { + return first.timeStamp <= second.timeStamp; + } + }; + + return std::lexicographical_compare(currentSourceTimeStamp.begin(), + currentSourceTimeStamp.end(), + sourceEntries.begin(), + sourceEntries.end(), + CompareTime{}); + } + + void updateCurrentSourceTimeStamps(const SourceEntries &sourceEntries) const + { + SourceTimeStamps sourceTimeStamps = newSourceTimeStamps(sourceEntries); + + for (SourceTimeStamp &newSourceTimeStamp : sourceTimeStamps) { + newSourceTimeStamp.timeStamp = m_getModifiedTime( + m_filePathCache.filePath(newSourceTimeStamp.sourceId)); + } + + auto split = sourceTimeStamps.insert(sourceTimeStamps.end(), + m_currentSourceTimeStamps.begin(), + m_currentSourceTimeStamps.end()); + std::inplace_merge(sourceTimeStamps.begin(), split, sourceTimeStamps.end()); + + m_currentSourceTimeStamps = sourceTimeStamps; + } + + SourceTimeStamps newSourceTimeStamps(const SourceEntries &sourceEntries) const + { + SourceEntries newSourceEntries; + newSourceEntries.reserve(sourceEntries.size()); + + class CompareSourceId + { + public: + bool operator()(SourceTimeStamp first, SourceTimeStamp second) + { + return first.sourceId < second.sourceId; + } + + bool operator()(::ClangBackEnd::SourceEntry first, ::ClangBackEnd::SourceEntry second) + { + return first.sourceId < second.sourceId; + } + + bool operator()(SourceTimeStamp first, ::ClangBackEnd::SourceEntry second) + { + return first.sourceId < second.sourceId; + } + + bool operator()(::ClangBackEnd::SourceEntry first, SourceTimeStamp second) + { + return first.sourceId < second.sourceId; + } + }; + + std::set_difference(sourceEntries.begin(), + sourceEntries.end(), + m_currentSourceTimeStamps.begin(), + m_currentSourceTimeStamps.end(), + std::back_inserter(newSourceEntries), + CompareSourceId{}); + + SourceTimeStamps newTimeStamps; + newTimeStamps.reserve(newSourceEntries.size()); + + std::transform(newSourceEntries.begin(), + newSourceEntries.end(), + std::back_inserter(newTimeStamps), + [](SourceEntry entry) { + return SourceTimeStamp{entry.sourceId, {}}; + }); + + return newTimeStamps; + } + +private: + mutable SourceTimeStamps m_currentSourceTimeStamps; + GetModifiedTime &m_getModifiedTime; + FilePathCachingInterface &m_filePathCache; +}; + +} // namespace ClangBackEnd diff --git a/src/libs/clangsupport/projectpartpchproviderinterface.h b/src/libs/clangsupport/modifiedtimecheckerinterface.h index 282e541cfd..a0e79b0701 100644 --- a/src/libs/clangsupport/projectpartpchproviderinterface.h +++ b/src/libs/clangsupport/modifiedtimecheckerinterface.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -25,26 +25,23 @@ #pragma once -#include "projectpartpch.h" - -#include <utils/optional.h> +#include "sourceentry.h" namespace ClangBackEnd { -class ProjectPartPchProviderInterface +template<typename SourceEntries = ::ClangBackEnd::SourceEntries> +class ModifiedTimeCheckerInterface { public: - ProjectPartPchProviderInterface() = default; - ProjectPartPchProviderInterface(const ProjectPartPchProviderInterface &) = delete; - ProjectPartPchProviderInterface &operator=(const ProjectPartPchProviderInterface &) = delete; - - virtual Utils::optional<ClangBackEnd::ProjectPartPch> projectPartPch( - ClangBackEnd::ProjectPartId projectPartId) const = 0; - virtual const ClangBackEnd::ProjectPartPchs &projectPartPchs() const = 0; + ModifiedTimeCheckerInterface() = default; + ModifiedTimeCheckerInterface(const ModifiedTimeCheckerInterface &) = delete; + ModifiedTimeCheckerInterface &operator=(const ModifiedTimeCheckerInterface &) = delete; + virtual bool isUpToDate(const SourceEntries &sourceEntries) const = 0; protected: - ~ProjectPartPchProviderInterface() = default; + ~ModifiedTimeCheckerInterface() = default; }; } // namespace ClangBackEnd + diff --git a/src/libs/clangsupport/pchmanagerclientproxy.h b/src/libs/clangsupport/pchmanagerclientproxy.h index 516b2e3a86..6dec4ecfca 100644 --- a/src/libs/clangsupport/pchmanagerclientproxy.h +++ b/src/libs/clangsupport/pchmanagerclientproxy.h @@ -42,9 +42,6 @@ public: PchManagerClientProxy(const PchManagerClientProxy&) = delete; const PchManagerClientProxy &operator=(const PchManagerClientProxy&) = delete; - PchManagerClientProxy(PchManagerClientProxy &&other) = default; - PchManagerClientProxy &operator=(PchManagerClientProxy &&other) = default; - void readMessages(); void alive() override; diff --git a/src/libs/clangsupport/pchpaths.h b/src/libs/clangsupport/pchpaths.h new file mode 100644 index 0000000000..048ec9da8d --- /dev/null +++ b/src/libs/clangsupport/pchpaths.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "filepath.h" + +namespace ClangBackEnd { + +class PchPaths +{ +public: + PchPaths() = default; + PchPaths(Utils::SmallStringView projectPchPath, Utils::SmallStringView systemPchPath) + : projectPchPath(FilePathView{projectPchPath}) + , systemPchPath(FilePathView{systemPchPath}) + {} + + friend bool operator==(const PchPaths &first, const PchPaths &second) + { + return first.projectPchPath == second.projectPchPath + && first.systemPchPath == second.systemPchPath; + } + +public: + FilePath projectPchPath; + FilePath systemPchPath; +}; + +} // namespace ClangBackEnd diff --git a/src/libs/clangsupport/precompiledheadersupdatedmessage.h b/src/libs/clangsupport/precompiledheadersupdatedmessage.h index 5a21b995df..5bd24dcd49 100644 --- a/src/libs/clangsupport/precompiledheadersupdatedmessage.h +++ b/src/libs/clangsupport/precompiledheadersupdatedmessage.h @@ -25,7 +25,10 @@ #pragma once -#include "projectpartpch.h" +#include "clangsupport_global.h" +#include "projectpartid.h" + +#include <utils/smallstringio.h> namespace ClangBackEnd { @@ -33,25 +36,26 @@ class PrecompiledHeadersUpdatedMessage { public: PrecompiledHeadersUpdatedMessage() = default; - PrecompiledHeadersUpdatedMessage(std::vector<ProjectPartPch> &&projectPartPchs) - : projectPartPchs(std::move(projectPartPchs)) - {} - - ProjectPartPchs takeProjectPartPchs() const + PrecompiledHeadersUpdatedMessage(ProjectPartId projectPartId) { - return std::move(projectPartPchs); + projectPartIds.push_back(projectPartId); } + PrecompiledHeadersUpdatedMessage(ProjectPartIds &&projectPartIds) + : projectPartIds(std::move(projectPartIds)) + {} + + ProjectPartIds takeProjectPartIds() const { return std::move(projectPartIds); } friend QDataStream &operator<<(QDataStream &out, const PrecompiledHeadersUpdatedMessage &message) { - out << message.projectPartPchs; + out << message.projectPartIds; return out; } friend QDataStream &operator>>(QDataStream &in, PrecompiledHeadersUpdatedMessage &message) { - in >> message.projectPartPchs; + in >> message.projectPartIds; return in; } @@ -59,16 +63,13 @@ public: friend bool operator==(const PrecompiledHeadersUpdatedMessage &first, const PrecompiledHeadersUpdatedMessage &second) { - return first.projectPartPchs == second.projectPartPchs; + return first.projectPartIds == second.projectPartIds; } - PrecompiledHeadersUpdatedMessage clone() const - { - return PrecompiledHeadersUpdatedMessage(Utils::clone(projectPartPchs)); - } + PrecompiledHeadersUpdatedMessage clone() const { return *this; } public: - std::vector<ProjectPartPch> projectPartPchs; + ProjectPartIds projectPartIds; }; CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const PrecompiledHeadersUpdatedMessage &message); diff --git a/src/libs/clangsupport/projectpartartefact.cpp b/src/libs/clangsupport/projectpartartefact.cpp index 7623f38796..56551693e1 100644 --- a/src/libs/clangsupport/projectpartartefact.cpp +++ b/src/libs/clangsupport/projectpartartefact.cpp @@ -33,8 +33,6 @@ namespace ClangBackEnd { - - Utils::SmallStringVector ProjectPartArtefact::toStringVector(Utils::SmallStringView jsonText) { if (jsonText.isEmpty()) diff --git a/src/libs/clangsupport/projectpartartefact.h b/src/libs/clangsupport/projectpartartefact.h index ac8c44a891..0d9bcf5c39 100644 --- a/src/libs/clangsupport/projectpartartefact.h +++ b/src/libs/clangsupport/projectpartartefact.h @@ -113,8 +113,8 @@ public: CompilerMacros compilerMacros; IncludeSearchPaths systemIncludeSearchPaths; IncludeSearchPaths projectIncludeSearchPaths; - Utils::Language language = Utils::Language::Cxx; - Utils::LanguageVersion languageVersion = Utils::LanguageVersion::CXX98; + Utils::Language language = Utils::Language::None; + Utils::LanguageVersion languageVersion = Utils::LanguageVersion::None; Utils::LanguageExtension languageExtension = Utils::LanguageExtension::None; }; diff --git a/src/libs/clangsupport/projectpartcontainer.h b/src/libs/clangsupport/projectpartcontainer.h index f1c64bd237..b2133dcaa2 100644 --- a/src/libs/clangsupport/projectpartcontainer.h +++ b/src/libs/clangsupport/projectpartcontainer.h @@ -147,7 +147,8 @@ public: first.sourcePathIds, first.language, first.languageVersion, - first.languageExtension) + first.languageExtension, + first.hasPrecompiledHeader) < std::tie(second.projectPartId, second.toolChainArguments, second.compilerMacros, @@ -157,7 +158,8 @@ public: second.sourcePathIds, second.language, second.languageVersion, - second.languageExtension); + second.languageExtension, + second.hasPrecompiledHeader); } ProjectPartContainer clone() const @@ -169,6 +171,7 @@ public: FilePathIds headerPathIds; FilePathIds sourcePathIds; bool updateIsDeferred = false; + bool hasPrecompiledHeader = true; }; using ProjectPartContainerReference = std::reference_wrapper<ProjectPartContainer>; diff --git a/src/libs/clangsupport/projectpartid.h b/src/libs/clangsupport/projectpartid.h index c372682baf..fc5f659605 100644 --- a/src/libs/clangsupport/projectpartid.h +++ b/src/libs/clangsupport/projectpartid.h @@ -54,7 +54,7 @@ public: return first.projectPathId < second.projectPathId; } - friend QDataStream &operator<<(QDataStream &out, const ProjectPartId &projectPathId) + friend QDataStream &operator<<(QDataStream &out, ProjectPartId projectPathId) { out << projectPathId.projectPathId; diff --git a/src/libs/clangsupport/projectpartpch.cpp b/src/libs/clangsupport/projectpartpch.cpp index aac672441c..9c870ac572 100644 --- a/src/libs/clangsupport/projectpartpch.cpp +++ b/src/libs/clangsupport/projectpartpch.cpp @@ -29,8 +29,7 @@ namespace ClangBackEnd { QDebug operator<<(QDebug debug, const ProjectPartPch &projectPartPch) { - debug.nospace() << "FileContainer(" << projectPartPch.projectPartId.projectPathId << ", " - << projectPartPch.pchPath << ")"; + debug.nospace() << "FileContainer(" << projectPartPch.projectPartId.projectPathId << ")"; return debug; } diff --git a/src/libs/clangsupport/projectpartpch.h b/src/libs/clangsupport/projectpartpch.h index c471b46b16..213247ae42 100644 --- a/src/libs/clangsupport/projectpartpch.h +++ b/src/libs/clangsupport/projectpartpch.h @@ -74,8 +74,7 @@ public: friend bool operator==(const ProjectPartPch &first, const ProjectPartPch &second) { - return first.projectPartId == second.projectPartId - && first.pchPath == second.pchPath; + return first.projectPartId == second.projectPartId && first.pchPath == second.pchPath; } ProjectPartPch clone() const diff --git a/src/libs/clangsupport/projectpartsstorage.h b/src/libs/clangsupport/projectpartsstorage.h index c91291bca2..e71bb0d51e 100644 --- a/src/libs/clangsupport/projectpartsstorage.h +++ b/src/libs/clangsupport/projectpartsstorage.h @@ -74,6 +74,14 @@ public: .template values<FilePathId>(1024, projectPartId.projectPathId); } + bool hasPrecompiledHeader(ProjectPartId projectPartId) const + { + auto value = fetchProjectPrecompiledHeaderPathStatement.template value<Utils::SmallString>( + projectPartId.projectPathId); + + return value && value->hasContent(); + } + ProjectPartContainers fetchProjectParts(const ProjectPartIds &projectPartIds) const override { try { @@ -88,6 +96,7 @@ public: if (value) { value->headerPathIds = fetchHeaders(projectPartId); value->sourcePathIds = fetchSources(projectPartId); + value->hasPrecompiledHeader = hasPrecompiledHeader(projectPartId); projectParts.push_back(*std::move(value)); } } @@ -125,7 +134,7 @@ public: } } - Utils::PathString fetchProjectPartName(ProjectPartId projectPartId) const + Utils::PathString fetchProjectPartName(ProjectPartId projectPartId) const override { try { Sqlite::DeferredTransaction transaction{database}; @@ -236,6 +245,22 @@ public: return statement.template value<ProjectPartArtefact, 8>(projectPartId.projectPathId); } + void resetIndexingTimeStamps(const ProjectPartContainers &projectsParts) override + { + try { + Sqlite::ImmediateTransaction transaction{database}; + + for (const ProjectPartContainer &projectPart : projectsParts) { + for (FilePathId sourcePathId : projectPart.sourcePathIds) + resetDependentIndexingTimeStampsStatement.write(sourcePathId.filePathId); + } + + transaction.commit(); + } catch (const Sqlite::StatementIsBusy &) { + resetIndexingTimeStamps(projectsParts); + } + } + Sqlite::TransactionInterface &transactionBackend() override { return database; } static Utils::SmallString toJson(const Utils::SmallStringVector &strings) @@ -332,5 +357,13 @@ public: "SELECT sourceId FROM projectPartsHeaders WHERE projectPartId = ?", database}; mutable ReadStatement fetchProjectPartsSourcesByIdStatement{ "SELECT sourceId FROM projectPartsSources WHERE projectPartId = ?", database}; + mutable ReadStatement fetchProjectPrecompiledHeaderPathStatement{ + "SELECT projectPchPath FROM precompiledHeaders WHERE projectPartId = ?", database}; + WriteStatement resetDependentIndexingTimeStampsStatement{ + "WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION SELECT " + "dependencySourceId FROM sourceDependencies, collectedDependencies WHERE " + "sourceDependencies.sourceId == collectedDependencies.sourceId) UPDATE fileStatuses SET " + "indexingTimeStamp = NULL WHERE sourceId IN (SELECT sourceId FROM collectedDependencies)", + database}; }; } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/projectpartsstorageinterface.h b/src/libs/clangsupport/projectpartsstorageinterface.h index 1127f70b1f..2d0675e657 100644 --- a/src/libs/clangsupport/projectpartsstorageinterface.h +++ b/src/libs/clangsupport/projectpartsstorageinterface.h @@ -63,6 +63,7 @@ public: virtual Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(FilePathId sourceId) const = 0; virtual Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact( ProjectPartId projectPartId) const = 0; + virtual void resetIndexingTimeStamps(const ProjectPartContainers &projectsParts) = 0; virtual Sqlite::TransactionInterface &transactionBackend() = 0; diff --git a/src/libs/clangsupport/refactoringdatabaseinitializer.h b/src/libs/clangsupport/refactoringdatabaseinitializer.h index efca925413..a7058d3204 100644 --- a/src/libs/clangsupport/refactoringdatabaseinitializer.h +++ b/src/libs/clangsupport/refactoringdatabaseinitializer.h @@ -177,6 +177,7 @@ public: Sqlite::Contraint::PrimaryKey); table.addColumn("size", Sqlite::ColumnType::Integer); table.addColumn("lastModified", Sqlite::ColumnType::Integer); + table.addColumn("indexingTimeStamp", Sqlite::ColumnType::Integer); table.initialize(database); } @@ -188,6 +189,7 @@ public: const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer); const Sqlite::Column &dependencySourceIdColumn = table.addColumn("dependencySourceId", Sqlite::ColumnType::Integer); table.addIndex({sourceIdColumn, dependencySourceIdColumn}); + table.addIndex({dependencySourceIdColumn, sourceIdColumn}); table.initialize(database); } diff --git a/src/libs/clangsupport/sourceentry.h b/src/libs/clangsupport/sourceentry.h new file mode 100644 index 0000000000..c593f1fcd3 --- /dev/null +++ b/src/libs/clangsupport/sourceentry.h @@ -0,0 +1,152 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <filepathid.h> + +#include <vector> + +namespace ClangBackEnd { + +enum class SourceType : unsigned char { + TopProjectInclude, + TopSystemInclude, + UserInclude, + ProjectInclude, + SystemInclude, + Source +}; + +enum class HasMissingIncludes : unsigned char { No, Yes }; + +class TimeStamp +{ + using int64 = long long; +public: + TimeStamp() = default; + TimeStamp(int64 value) + : value(value) + {} + + operator int64() const + { + return value; + } + + int64 value = -1; +}; + +class SourceTimeStamp +{ + using int64 = long long; +public: + SourceTimeStamp(int sourceId, int64 lastModified) + : timeStamp(lastModified) + , sourceId(sourceId) + {} + + SourceTimeStamp(FilePathId sourceId, TimeStamp lastModified) + : timeStamp(lastModified) + , sourceId(sourceId) + {} + + friend bool operator<(SourceTimeStamp first, SourceTimeStamp second) + { + return first.sourceId < second.sourceId; + } + + friend bool operator<(SourceTimeStamp first, FilePathId second) + { + return first.sourceId < second; + } + + friend bool operator<(FilePathId first, SourceTimeStamp second) + { + return first < second.sourceId; + } + + friend bool operator==(SourceTimeStamp first, SourceTimeStamp second) + { + return first.sourceId == second.sourceId && first.timeStamp == second.timeStamp; + } + + friend bool operator!=(SourceTimeStamp first, SourceTimeStamp second) + { + return !(first == second); + } + +public: + TimeStamp timeStamp; + FilePathId sourceId; +}; + +using SourceTimeStamps = std::vector<SourceTimeStamp>; + +class SourceEntry +{ + using int64 = long long; + +public: + SourceEntry(int sourceId, int64 timeStamp, int sourceType, int hasMissingIncludes) + : timeStamp(timeStamp) + , sourceId(sourceId) + , sourceType(static_cast<SourceType>(sourceType)) + , hasMissingIncludes(static_cast<HasMissingIncludes>(hasMissingIncludes)) + {} + + SourceEntry(FilePathId sourceId, + SourceType sourceType, + TimeStamp timeStamp, + HasMissingIncludes hasMissingIncludes = HasMissingIncludes::No) + : timeStamp(timeStamp) + , sourceId(sourceId) + , sourceType(sourceType) + , hasMissingIncludes(hasMissingIncludes) + {} + + friend bool operator<(SourceEntry first, SourceEntry second) { + return first.sourceId < second.sourceId; + } + + friend bool operator==(SourceEntry first, SourceEntry second) + { + return first.sourceId == second.sourceId && first.sourceType == second.sourceType + && first.timeStamp == second.timeStamp; + } + + friend bool operator!=(SourceEntry first, SourceEntry second) { return !(first == second); } + +public: + TimeStamp timeStamp; + FilePathId sourceId; + SourceType sourceType = SourceType::UserInclude; + HasMissingIncludes hasMissingIncludes = HasMissingIncludes::No; +}; + +using SourceEntries = std::vector<SourceEntry>; +using SourceEntryReference = std::reference_wrapper<SourceEntry>; +using SourceEntryReferences = std::vector<SourceEntryReference>; +} // namespace ClangBackEnd |