diff options
27 files changed, 229 insertions, 157 deletions
diff --git a/src/libs/clangbackendipc/clangbackendipc-lib.pri b/src/libs/clangbackendipc/clangbackendipc-lib.pri index 36afd9ae70..9664775dd1 100644 --- a/src/libs/clangbackendipc/clangbackendipc-lib.pri +++ b/src/libs/clangbackendipc/clangbackendipc-lib.pri @@ -155,6 +155,7 @@ HEADERS += \ $$PWD/pchmanagerclientproxy.h \ $$PWD/projectpartpch.h \ $$PWD/precompiledheadersupdatedmessage.h \ + $$PWD/stringcache.h \ $$PWD/removepchprojectpartsmessage.h \ $$PWD/clangcodemodelclientmessages.h \ $$PWD/clangcodemodelservermessages.h \ diff --git a/src/libs/clangbackendipc/filepath.h b/src/libs/clangbackendipc/filepath.h index d435441a13..717d020790 100644 --- a/src/libs/clangbackendipc/filepath.h +++ b/src/libs/clangbackendipc/filepath.h @@ -37,66 +37,62 @@ class FilePath { public: FilePath() = default; - explicit FilePath(Utils::SmallString &&filePath) + explicit FilePath(Utils::PathString &&filePath) + : m_path(std::move(filePath)) { - auto foundReverse = std::find(filePath.rbegin(), filePath.rend(), '/'); + auto foundReverse = std::find(m_path.rbegin(), m_path.rend(), '/'); auto found = foundReverse.base(); + --found; - Utils::SmallString fileName(found, filePath.end()); - if (foundReverse != filePath.rend()) - filePath.resize(std::size_t(std::distance(filePath.begin(), --found))); - - directory_ = std::move(filePath); - name_ = std::move(fileName); + m_slashIndex = std::size_t(std::distance(m_path.begin(), found)); } - explicit FilePath(const QString &filePath) - : FilePath(Utils::SmallString(filePath)) + explicit FilePath(const Utils::PathString &filePath) + : FilePath(filePath.clone()) { } - FilePath(Utils::SmallString &&directory, Utils::SmallString &&name) - : directory_(std::move(directory)), - name_(std::move(name)) - {} - - const Utils::SmallString &directory() const + explicit FilePath(Utils::PathString &&filePath, std::size_t slashIndex) + : m_path(std::move(filePath)), + m_slashIndex(slashIndex) { - return directory_; } - Utils::SmallString takeDirectory() + explicit FilePath(const QString &filePath) + : FilePath(Utils::PathString(filePath)) { - return std::move(directory_); } - const Utils::SmallString &name() const + FilePath(const Utils::PathString &directory, const Utils::PathString &name) + : m_path({std::move(directory), "/", std::move(name)}), + m_slashIndex(directory.size()) + {} + + Utils::SmallStringView directory() const { - return name_; + return m_path.mid(0, m_slashIndex); } - Utils::SmallString takeName() + Utils::SmallStringView name() const { - return std::move(name_); + return m_path.mid(m_slashIndex + 1, m_path.size() - m_slashIndex - 1); } - Utils::PathString path() const + const Utils::PathString &path() const { - return {directory_, "/", name_}; + return m_path; } friend QDataStream &operator<<(QDataStream &out, const FilePath &filePath) { - out << filePath.directory_; - out << filePath.name_; + out << filePath.m_path; return out; } friend QDataStream &operator>>(QDataStream &in, FilePath &filePath) { - in >> filePath.directory_; - in >> filePath.name_; + in >> filePath.m_path; return in; } @@ -110,24 +106,22 @@ public: friend bool operator==(const FilePath &first, const FilePath &second) { - return first.name_ == second.name_ - && first.directory_ == second.directory_; + return first.m_path == second.m_path; } friend bool operator<(const FilePath &first, const FilePath &second) { - return std::tie(first.name_, first.directory_) - < std::tie(second.name_, second.directory_); + return first.m_path < second.m_path; } FilePath clone() const { - return FilePath(directory_.clone(), name_.clone()); + return FilePath(m_path.clone(), m_slashIndex); } private: - Utils::SmallString directory_; - Utils::SmallString name_; + Utils::PathString m_path = "/"; + std::size_t m_slashIndex = 0; }; CMBIPC_EXPORT QDebug operator<<(QDebug debug, const FilePath &filePath); diff --git a/src/libs/clangbackendipc/sourcefilepathcontainerbase.h b/src/libs/clangbackendipc/sourcefilepathcontainerbase.h index af5f8b570c..ec5b78e9a7 100644 --- a/src/libs/clangbackendipc/sourcefilepathcontainerbase.h +++ b/src/libs/clangbackendipc/sourcefilepathcontainerbase.h @@ -42,13 +42,10 @@ public: { } - void insertFilePath(uint fileId, Utils::SmallString &&fileDirectory, Utils::SmallString &&fileName) + void insertFilePath(uint fileId, Utils::PathString &&filePath) { - if (m_filePathHash.find(fileId) == m_filePathHash.end()) { - m_filePathHash.emplace(std::piecewise_construct, - std::forward_as_tuple(fileId), - std::forward_as_tuple(std::move(fileDirectory), std::move(fileName))); - } + if (m_filePathHash.find(fileId) == m_filePathHash.end()) + m_filePathHash.emplace(fileId, std::move(filePath)); } void reserve(std::size_t size) diff --git a/src/libs/clangbackendipc/sourcelocationcontainerv2.cpp b/src/libs/clangbackendipc/sourcelocationcontainerv2.cpp index b65803e7c6..3206daf2b5 100644 --- a/src/libs/clangbackendipc/sourcelocationcontainerv2.cpp +++ b/src/libs/clangbackendipc/sourcelocationcontainerv2.cpp @@ -46,10 +46,10 @@ QDebug operator<<(QDebug debug, const SourceLocationContainer &container) std::ostream &operator<<(std::ostream &os, const SourceLocationContainer &container) { os << "(" + << container.fileHash() << ", " << container.line() << ", " << container.column() << ", " - << container.offset() << ", " - << container.fileHash() + << container.offset() << ")"; return os; diff --git a/src/libs/clangbackendipc/sourcerangewithtextcontainer.h b/src/libs/clangbackendipc/sourcerangewithtextcontainer.h index 12b25084c3..82d17f884a 100644 --- a/src/libs/clangbackendipc/sourcerangewithtextcontainer.h +++ b/src/libs/clangbackendipc/sourcerangewithtextcontainer.h @@ -110,6 +110,8 @@ private: Utils::SmallString m_text; }; +using SourceRangeWithTextContainers = std::vector<SourceRangeWithTextContainer>; + CMBIPC_EXPORT QDebug operator<<(QDebug debug, const SourceRangeWithTextContainer &container); std::ostream &operator<<(std::ostream &os, const SourceRangeWithTextContainer &container); } // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/stringcache.h b/src/libs/clangbackendipc/stringcache.h index a85c314700..7b4230b577 100644 --- a/src/tools/clangpchmanagerbackend/source/stringcache.h +++ b/src/libs/clangbackendipc/stringcache.h @@ -25,16 +25,26 @@ #pragma once -#include "clangpchmanagerbackend_global.h" - #include <utils/smallstringview.h> #include <algorithm> +#include <mutex> #include <vector> namespace ClangBackEnd { -template <typename StringType> +class NonLockingMutex +{ +public: + constexpr NonLockingMutex() noexcept {} + NonLockingMutex(const NonLockingMutex&) = delete; + NonLockingMutex& operator=(const NonLockingMutex&) = delete; + void lock() {} + void unlock() {} +}; + +template <typename StringType, + typename Mutex = NonLockingMutex> class StringCache { class StringCacheEntry @@ -79,6 +89,8 @@ public: uint stringId(Utils::SmallStringView stringView) { + std::lock_guard<Mutex> lock(m_mutex); + Found found = find(stringView); if (!found.wasFound) @@ -89,6 +101,8 @@ public: std::vector<uint> stringIds(const std::vector<StringType> &strings) { + std::lock_guard<Mutex> lock(m_mutex); + std::vector<uint> ids; ids.reserve(strings.size()); @@ -102,11 +116,15 @@ public: const StringType &string(uint id) const { + std::lock_guard<Mutex> lock(m_mutex); + return m_strings.at(m_indices.at(id)).string; } std::vector<StringType> strings(const std::vector<uint> &ids) const { + std::lock_guard<Mutex> lock(m_mutex); + std::vector<StringType> strings; strings.reserve(ids.size()); @@ -155,6 +173,7 @@ private: private: StringCacheEntries m_strings; std::vector<uint> m_indices; + mutable Mutex m_mutex; }; } // namespace ClangBackEnd diff --git a/src/libs/utils/smallstringio.h b/src/libs/utils/smallstringio.h index 26424b22fe..8dabbcc4d0 100644 --- a/src/libs/utils/smallstringio.h +++ b/src/libs/utils/smallstringio.h @@ -68,8 +68,8 @@ QDataStream &operator>>(QDataStream &in, BasicSmallString<Size> &string) return in; } -inline -QDebug &operator<<(QDebug &debug, const SmallString &string) +template <typename String> +QDebug &operator<<(QDebug &debug, const String &string) { using QT_PREPEND_NAMESPACE(operator<<); diff --git a/src/libs/utils/smallstringview.h b/src/libs/utils/smallstringview.h index 2d445501c2..3e11497ed3 100644 --- a/src/libs/utils/smallstringview.h +++ b/src/libs/utils/smallstringview.h @@ -104,6 +104,11 @@ public: return const_reverse_iterator(begin() - static_cast<std::size_t>(1)); } + operator std::string() const + { + return std::string(data(), size()); + } + private: const char *m_pointer; size_type m_size; diff --git a/src/plugins/clangrefactoring/refactoringclient.cpp b/src/plugins/clangrefactoring/refactoringclient.cpp index 83b058d626..4cb954e231 100644 --- a/src/plugins/clangrefactoring/refactoringclient.cpp +++ b/src/plugins/clangrefactoring/refactoringclient.cpp @@ -104,19 +104,6 @@ void RefactoringClient::setRefactoringConnectionClient( this->connectionClient = connectionClient; } -namespace { - -Utils::SmallString concatenateFilePath(const ClangBackEnd::FilePath &filePath) -{ - Utils::SmallString concatenatedFilePath = filePath.directory().clone(); - concatenatedFilePath.append("/"); - concatenatedFilePath.append(filePath.name().clone()); - - return concatenatedFilePath; -} - -} - std::unordered_map<uint, QString> RefactoringClient::convertFilePaths( const ClangBackEnd::FilePathDict &filePaths) { @@ -126,7 +113,7 @@ std::unordered_map<uint, QString> RefactoringClient::convertFilePaths( auto convertFilePath = [] (const ClangBackEnd::FilePathDict::value_type &dictonaryEntry) { return std::make_pair(dictonaryEntry.first, - concatenateFilePath(dictonaryEntry.second).toQString()); + dictonaryEntry.second.path().toQString()); }; std::transform(filePaths.begin(), diff --git a/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri index 2bb0d0ab7b..926280a5fa 100644 --- a/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri +++ b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri @@ -19,7 +19,6 @@ HEADERS += \ $$PWD/environment.h \ $$PWD/clangpathwatcher.h \ $$PWD/projectparts.h \ - $$PWD/stringcache.h \ $$PWD/idpaths.h \ $$PWD/pchcreatorinterface.h \ $$PWD/clangpathwatcherinterface.h \ diff --git a/src/tools/clangrefactoringbackend/source/clangquery.cpp b/src/tools/clangrefactoringbackend/source/clangquery.cpp index d24b981f45..be93b61a1a 100644 --- a/src/tools/clangrefactoringbackend/source/clangquery.cpp +++ b/src/tools/clangrefactoringbackend/source/clangquery.cpp @@ -30,27 +30,15 @@ #include <sourcerangescontainer.h> -#include <QTime> +#include <stringcache.h> -#if defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-parameter" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning( disable : 4100 ) -#endif +#include <QTime> #include <clang/ASTMatchers/ASTMatchers.h> #include <clang/ASTMatchers/ASTMatchFinder.h> #include <clang/ASTMatchers/Dynamic/Diagnostics.h> #include <clang/ASTMatchers/Dynamic/Parser.h> -#if defined(__GNUC__) -# pragma GCC diagnostic pop -#elif defined(_MSC_VER) -# pragma warning(pop) -#endif - using clang::ast_matchers::dynamic::Diagnostics; using clang::ast_matchers::dynamic::Parser; using clang::ast_matchers::BoundNodes; @@ -66,8 +54,10 @@ struct CollectBoundNodes : MatchFinder::MatchCallback { } }; -ClangQuery::ClangQuery(Utils::SmallString &&query) - : query(std::move(query)) +ClangQuery::ClangQuery(StringCache<Utils::PathString, std::mutex> &filePathCache, + Utils::SmallString &&query) + : query(std::move(query)), + filePathCache(filePathCache) { } @@ -226,6 +216,7 @@ void ClangQuery::matchLocation( SourceRangeExtractor extractor(ast->getSourceManager(), ast->getLangOpts(), + filePathCache, sourceRangesContainer); extractor.addSourceRanges(sourceRanges); diff --git a/src/tools/clangrefactoringbackend/source/clangquery.h b/src/tools/clangrefactoringbackend/source/clangquery.h index 93190449a5..20b38a7ab1 100644 --- a/src/tools/clangrefactoringbackend/source/clangquery.h +++ b/src/tools/clangrefactoringbackend/source/clangquery.h @@ -30,6 +30,8 @@ #include <sourcerangescontainer.h> #include <dynamicastmatcherdiagnosticcontainer.h> +#include <stringcache.h> + namespace clang { namespace ast_matchers { namespace dynamic { @@ -49,7 +51,7 @@ namespace ClangBackEnd { class ClangQuery : public ClangTool { public: - ClangQuery(Utils::SmallString &&query={}); + ClangQuery(StringCache<Utils::PathString, std::mutex> &filePathCache, Utils::SmallString &&query={}); void setQuery(Utils::SmallString &&query); @@ -67,6 +69,7 @@ private: SourceRangesContainer sourceRangesContainer; Utils::SmallString query; std::vector<DynamicASTMatcherDiagnosticContainer> diagnosticContainers_; + StringCache<Utils::PathString, std::mutex> &filePathCache; }; } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/clangquerygatherer.cpp b/src/tools/clangrefactoringbackend/source/clangquerygatherer.cpp index cbf9a9c70c..09c96a69b5 100644 --- a/src/tools/clangrefactoringbackend/source/clangquerygatherer.cpp +++ b/src/tools/clangrefactoringbackend/source/clangquerygatherer.cpp @@ -29,10 +29,12 @@ namespace ClangBackEnd { -ClangQueryGatherer::ClangQueryGatherer(std::vector<V2::FileContainer> &&sources, +ClangQueryGatherer::ClangQueryGatherer(StringCache<Utils::PathString, std::mutex> *filePathCache, + std::vector<V2::FileContainer> &&sources, std::vector<V2::FileContainer> &&unsaved, Utils::SmallString &&query) - : m_sources(std::move(sources)), + : m_filePathCache(filePathCache), + m_sources(std::move(sources)), m_unsaved(std::move(unsaved)), m_query(std::move(query)) { @@ -40,11 +42,12 @@ ClangQueryGatherer::ClangQueryGatherer(std::vector<V2::FileContainer> &&sources, SourceRangesAndDiagnosticsForQueryMessage ClangQueryGatherer::createSourceRangesAndDiagnosticsForSource( + StringCache<Utils::PathString, std::mutex> *filePathCache, V2::FileContainer &&source, const std::vector<V2::FileContainer> &unsaved, Utils::SmallString &&query) { - ClangQuery clangQuery(std::move(query)); + ClangQuery clangQuery(*filePathCache, std::move(query)); clangQuery.addFile(source.filePath().directory(), source.filePath().name(), @@ -65,7 +68,8 @@ bool ClangQueryGatherer::canCreateSourceRangesAndDiagnostics() const SourceRangesAndDiagnosticsForQueryMessage ClangQueryGatherer::createNextSourceRangesAndDiagnostics() { - auto message = createSourceRangesAndDiagnosticsForSource(std::move(m_sources.back()), + auto message = createSourceRangesAndDiagnosticsForSource(m_filePathCache, + std::move(m_sources.back()), m_unsaved, m_query.clone()); m_sources.pop_back(); @@ -77,6 +81,7 @@ ClangQueryGatherer::Future ClangQueryGatherer::startCreateNextSourceRangesAndDia { Future future = std::async(std::launch::async, createSourceRangesAndDiagnosticsForSource, + m_filePathCache, std::move(m_sources.back()), m_unsaved, m_query.clone()); diff --git a/src/tools/clangrefactoringbackend/source/clangquerygatherer.h b/src/tools/clangrefactoringbackend/source/clangquerygatherer.h index a7ba8fac79..b937056379 100644 --- a/src/tools/clangrefactoringbackend/source/clangquerygatherer.h +++ b/src/tools/clangrefactoringbackend/source/clangquerygatherer.h @@ -27,6 +27,7 @@ #include <sourcerangesanddiagnosticsforquerymessage.h> #include <filecontainerv2.h> +#include <stringcache.h> #include <future> @@ -38,16 +39,16 @@ public: using Future = std::future<SourceRangesAndDiagnosticsForQueryMessage>; ClangQueryGatherer() = default; - ClangQueryGatherer(std::vector<V2::FileContainer> &&sources, + ClangQueryGatherer(StringCache<Utils::PathString, std::mutex> *filePathCache, + std::vector<V2::FileContainer> &&sources, std::vector<V2::FileContainer> &&unsaved, Utils::SmallString &&query); - static - SourceRangesAndDiagnosticsForQueryMessage createSourceRangesAndDiagnosticsForSource( + static SourceRangesAndDiagnosticsForQueryMessage createSourceRangesAndDiagnosticsForSource( + StringCache<Utils::PathString, std::mutex> *filePathCache, V2::FileContainer &&source, const std::vector<V2::FileContainer> &unsaved, Utils::SmallString &&query); - bool canCreateSourceRangesAndDiagnostics() const; SourceRangesAndDiagnosticsForQueryMessage createNextSourceRangesAndDiagnostics(); Future startCreateNextSourceRangesAndDiagnosticsMessage(); @@ -66,6 +67,7 @@ protected: std::vector<Future> finishedFutures(); private: + StringCache<Utils::PathString, std::mutex> *m_filePathCache = nullptr; std::vector<V2::FileContainer> m_sources; std::vector<V2::FileContainer> m_unsaved; Utils::SmallString m_query; diff --git a/src/tools/clangrefactoringbackend/source/clangtool.cpp b/src/tools/clangrefactoringbackend/source/clangtool.cpp index dd4b6c57a3..2ffad73965 100644 --- a/src/tools/clangrefactoringbackend/source/clangtool.cpp +++ b/src/tools/clangrefactoringbackend/source/clangtool.cpp @@ -84,23 +84,12 @@ template void ClangTool::addFiles<Utils::PathStringVector>(const Utils::PathStringVector &filePaths, const Utils::SmallStringVector &arguments); -namespace { -Utils::SmallString toNativeFilePath(const FilePath &filePath) -{ - Utils::SmallString filePathString = filePath.directory().clone(); - filePathString.append("/"); - filePathString.append(filePath.name()); - - return toNativePath(std::move(filePathString)); -} -} - void ClangTool::addUnsavedFiles(const V2::FileContainers &unsavedFiles) { unsavedFileContents.reserve(unsavedFileContents.size() + unsavedFiles.size()); auto convertToUnsavedFileContent = [] (const V2::FileContainer &unsavedFile) { - return UnsavedFileContent{toNativeFilePath(unsavedFile.filePath()), + return UnsavedFileContent{toNativePath(unsavedFile.filePath().path().clone()), unsavedFile.unsavedFileContent().clone()}; }; @@ -111,7 +100,8 @@ void ClangTool::addUnsavedFiles(const V2::FileContainers &unsavedFiles) } namespace { -llvm::StringRef toStringRef(const Utils::SmallString &string) +template <typename String> +llvm::StringRef toStringRef(const String &string) { return llvm::StringRef(string.data(), string.size()); } diff --git a/src/tools/clangrefactoringbackend/source/clangtool.h b/src/tools/clangrefactoringbackend/source/clangtool.h index c7ee2a83e0..c643920914 100644 --- a/src/tools/clangrefactoringbackend/source/clangtool.h +++ b/src/tools/clangrefactoringbackend/source/clangtool.h @@ -77,13 +77,13 @@ struct FileContent struct UnsavedFileContent { - UnsavedFileContent(Utils::SmallString &&filePath, + UnsavedFileContent(Utils::PathString &&filePath, Utils::SmallString &&content) : filePath(std::move(filePath)), content(std::move(content)) {} - Utils::SmallString filePath; + Utils::PathString filePath; Utils::SmallString content; }; diff --git a/src/tools/clangrefactoringbackend/source/refactoringserver.cpp b/src/tools/clangrefactoringbackend/source/refactoringserver.cpp index 58e944784d..cf233baf34 100644 --- a/src/tools/clangrefactoringbackend/source/refactoringserver.cpp +++ b/src/tools/clangrefactoringbackend/source/refactoringserver.cpp @@ -37,6 +37,7 @@ #include <QCoreApplication> #include <functional> +#include <atomic> namespace ClangBackEnd { @@ -125,7 +126,7 @@ void RefactoringServer::gatherSourceRangesAndDiagnosticsForQueryMessages( uint freeProcessors = std::thread::hardware_concurrency(); #endif - m_gatherer = ClangQueryGatherer(std::move(sources), std::move(unsaved), std::move(query)); + m_gatherer = ClangQueryGatherer(&m_filePathCache, std::move(sources), std::move(unsaved), std::move(query)); m_gatherer.setProcessingSlotCount(freeProcessors); m_pollTimer.start(); diff --git a/src/tools/clangrefactoringbackend/source/refactoringserver.h b/src/tools/clangrefactoringbackend/source/refactoringserver.h index e3b40d3c56..1befa07621 100644 --- a/src/tools/clangrefactoringbackend/source/refactoringserver.h +++ b/src/tools/clangrefactoringbackend/source/refactoringserver.h @@ -30,7 +30,12 @@ #include <refactoringserverinterface.h> #include <QTimer> +#include <stringcache.h> +#include <utils/smallstring.h> + +#include <future> +#include <mutex> #include <vector> namespace ClangBackEnd { @@ -65,6 +70,7 @@ private: Utils::SmallString &&query); private: + StringCache<Utils::PathString, std::mutex> m_filePathCache; ClangQueryGatherer m_gatherer; QTimer m_pollTimer; }; diff --git a/src/tools/clangrefactoringbackend/source/sourcelocationsutils.h b/src/tools/clangrefactoringbackend/source/sourcelocationsutils.h index 78076f5f2b..df07b42daa 100644 --- a/src/tools/clangrefactoringbackend/source/sourcelocationsutils.h +++ b/src/tools/clangrefactoringbackend/source/sourcelocationsutils.h @@ -53,7 +53,7 @@ namespace ClangBackEnd { inline -llvm::SmallString<256> absolutePath(const llvm::StringRef &path) +llvm::SmallString<256> absolutePath(clang::StringRef path) { llvm::SmallString<256> absolutePath(path); @@ -64,9 +64,9 @@ llvm::SmallString<256> absolutePath(const llvm::StringRef &path) } template <typename Container> -Utils::SmallString fromNativePath(Container container) +Utils::PathString fromNativePath(Container container) { - Utils::SmallString path(container.data(), container.size()); + Utils::PathString path(container.data(), container.size()); #ifdef _WIN32 std::replace(path.begin(), path.end(), '\\', '/'); @@ -89,13 +89,9 @@ void appendSourceLocationsToSourceLocationsContainer( const auto fileId = decomposedLoction.first; const auto offset = decomposedLoction.second; const auto fileEntry = sourceManager.getFileEntryForID(fileId); - auto filePath = absolutePath(fileEntry->getName()); - const auto fileName = llvm::sys::path::filename(filePath); - llvm::sys::path::remove_filename(filePath); sourceLocationsContainer.insertFilePath(fileId.getHashValue(), - fromNativePath(filePath), - fromNativePath(fileName)); + fromNativePath(fileEntry->tryGetRealPathName())); sourceLocationsContainer.insertSourceLocation(fileId.getHashValue(), fullSourceLocation.getSpellingLineNumber(), fullSourceLocation.getSpellingColumnNumber(), diff --git a/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp index 18b6288cae..e83f6a3c38 100644 --- a/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp +++ b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp @@ -51,11 +51,14 @@ namespace ClangBackEnd { -SourceRangeExtractor::SourceRangeExtractor(const clang::SourceManager &sourceManager, - const clang::LangOptions &languageOptions, - SourceRangesContainer &sourceRangesContainer) +SourceRangeExtractor::SourceRangeExtractor( + const clang::SourceManager &sourceManager, + const clang::LangOptions &languageOptions, + ClangBackEnd::StringCache<Utils::PathString, std::mutex> &filePathCache, + SourceRangesContainer &sourceRangesContainer) : sourceManager(sourceManager), languageOptions(languageOptions), + filePathCache(filePathCache), sourceRangesContainer(sourceRangesContainer) { } @@ -123,19 +126,16 @@ const clang::SourceRange SourceRangeExtractor::extendSourceRangeToLastTokenEnd(c return {sourceRange.getBegin(), endLocation}; } -void SourceRangeExtractor::insertSourceRange(uint fileHash, - Utils::SmallString &&directoryPath, - Utils::SmallString &&fileName, +void SourceRangeExtractor::insertSourceRange(uint fileId, + Utils::PathString &&filePath, const clang::FullSourceLoc &startLocation, uint startOffset, const clang::FullSourceLoc &endLocation, uint endOffset, Utils::SmallString &&lineSnippet) { - sourceRangesContainer.insertFilePath(fileHash, - std::move(directoryPath), - std::move(fileName)); - sourceRangesContainer.insertSourceRange(fileHash, + sourceRangesContainer.insertFilePath(fileId, std::move(filePath)); + sourceRangesContainer.insertSourceRange(fileId, startLocation.getSpellingLineNumber(), startLocation.getSpellingColumnNumber(), startOffset, @@ -145,6 +145,17 @@ void SourceRangeExtractor::insertSourceRange(uint fileHash, std::move(lineSnippet)); } +uint SourceRangeExtractor::findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const +{ + auto found = m_fileIdMapping.find(fileId.getHashValue()); + if (found != m_fileIdMapping.end()) { + return found->second; + } + + auto filePath = absolutePath(fileEntry->tryGetRealPathName()); + return filePathCache.stringId(fromNativePath(filePath)); +} + void SourceRangeExtractor::addSourceRange(const clang::SourceRange &sourceRange) { auto extendedSourceRange = extendSourceRangeToLastTokenEnd(sourceRange); @@ -158,15 +169,13 @@ void SourceRangeExtractor::addSourceRange(const clang::SourceRange &sourceRange) const auto startOffset = startDecomposedLoction.second; const auto endOffset = endDecomposedLoction.second; const auto fileEntry = sourceManager.getFileEntryForID(fileId); - auto filePath = absolutePath(fileEntry->getName()); - const auto fileName = llvm::sys::path::filename(filePath); - llvm::sys::path::remove_filename(filePath); + Utils::SmallString lineSnippet = getExpandedText(startSourceLocation.getBufferData(), startOffset, endOffset); - insertSourceRange(fileId.getHashValue(), - fromNativePath(filePath), - {fileName.data(), fileName.size()}, + + insertSourceRange(findFileId(fileId, fileEntry), + fromNativePath(fileEntry->tryGetRealPathName()), startSourceLocation, startOffset, endSourceLocation, diff --git a/src/tools/clangrefactoringbackend/source/sourcerangeextractor.h b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.h index 5bd6cf75ab..7a07e5c3f8 100644 --- a/src/tools/clangrefactoringbackend/source/sourcerangeextractor.h +++ b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.h @@ -25,9 +25,14 @@ #pragma once +#include <stringcache.h> + +#include <filepath.h> + #include <utils/smallstringfwd.h> #include <vector> +#include <unordered_map> using uint = unsigned int; @@ -40,6 +45,8 @@ class SourceManager; class LangOptions; class SourceRange; class FullSourceLoc; +class FileID; +class FileEntry; } namespace ClangBackEnd { @@ -52,6 +59,7 @@ class SourceRangeExtractor public: SourceRangeExtractor(const clang::SourceManager &sourceManager, const clang::LangOptions &languageOptions, + ClangBackEnd::StringCache<Utils::PathString, std::mutex> &filePathCache, SourceRangesContainer &sourceRangesContainer); void addSourceRange(const clang::SourceRange &sourceRange); @@ -66,18 +74,21 @@ public: const clang::SourceRange extendSourceRangeToLastTokenEnd(const clang::SourceRange sourceRange); private: - void insertSourceRange(uint fileHash, - Utils::SmallString &&directoryPath, - Utils::SmallString &&fileName, + void insertSourceRange(uint fileId, + Utils::PathString &&filePath, const clang::FullSourceLoc &startLocation, uint startOffset, const clang::FullSourceLoc &endLocation, uint endOffset, Utils::SmallString &&lineSnippet); + uint findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const; + private: + mutable std::unordered_map<uint, uint> m_fileIdMapping; const clang::SourceManager &sourceManager; const clang::LangOptions &languageOptions; + ClangBackEnd::StringCache<Utils::PathString, std::mutex> &filePathCache; SourceRangesContainer &sourceRangesContainer; }; diff --git a/tests/unit/unittest/clangquery-test.cpp b/tests/unit/unittest/clangquery-test.cpp index b71e267697..39f82e0955 100644 --- a/tests/unit/unittest/clangquery-test.cpp +++ b/tests/unit/unittest/clangquery-test.cpp @@ -29,7 +29,10 @@ #include <clangquery.h> +#include <mutex> + using ClangBackEnd::ClangQuery; +using ClangBackEnd::StringCache; using testing::IsEmpty; using testing::Not; @@ -43,8 +46,9 @@ protected: void SetUp() override; protected: - ::ClangQuery simpleFunctionQuery; - ::ClangQuery simpleClassQuery; + StringCache<Utils::PathString, std::mutex> filePathCache; + ::ClangQuery simpleFunctionQuery{filePathCache}; + ::ClangQuery simpleClassQuery{filePathCache}; }; using ClangQuerySlowTest = ClangQuery; @@ -77,7 +81,7 @@ TEST_F(ClangQuerySlowTest, RootSourceRangeForSimpleFunctionDeclarationRange) TEST_F(ClangQuerySlowTest, SourceRangeInUnsavedFileDeclarationRange) { - ::ClangQuery query; + ::ClangQuery query(filePathCache); query.addFile(TESTDATA_DIR, "query_simplefunction.cpp", "#include \"unsaved.h\"", {"cc", "query_simplefunction.cpp", "-std=c++14"}); query.setQuery("functionDecl()"); ClangBackEnd::V2::FileContainer unsavedFile{{TESTDATA_DIR, "unsaved.h"}, "void unsaved();", {}}; @@ -91,7 +95,7 @@ TEST_F(ClangQuerySlowTest, SourceRangeInUnsavedFileDeclarationRange) TEST_F(ClangQuerySlowTest, DISABLED_SourceRangeInUnsavedFileDeclarationRangeOverride) // seems not to work in Clang { - ::ClangQuery query; + ::ClangQuery query(filePathCache); query.addFile(TESTDATA_DIR, "query_simplefunction.cpp", "void f() {}", {"cc", "query_simplefunction.cpp", "-std=c++14"}); query.setQuery("functionDecl()"); ClangBackEnd::V2::FileContainer unsavedFile{{TESTDATA_DIR, "query_simplefunction.cpp"}, "void unsaved();", {}}; diff --git a/tests/unit/unittest/clangquerygatherer-test.cpp b/tests/unit/unittest/clangquerygatherer-test.cpp index 089f273f06..0e24e4fa6d 100644 --- a/tests/unit/unittest/clangquerygatherer-test.cpp +++ b/tests/unit/unittest/clangquerygatherer-test.cpp @@ -71,6 +71,7 @@ protected: void SetUp() override; protected: + ClangBackEnd::StringCache<Utils::PathString, std::mutex> filePathCache; Utils::SmallString sourceContent{"#include \"query_simplefunction.h\"\nvoid f()\n {}"}; FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"}, sourceContent.clone(), @@ -80,15 +81,16 @@ protected: unsavedContent.clone(), {}}; Utils::SmallString query{"functionDecl()"}; - ClangBackEnd::ClangQueryGatherer gatherer{{source.clone()}, {unsaved.clone()}, query.clone()}; - ClangBackEnd::ClangQueryGatherer manyGatherer{{source.clone(), source.clone(), source.clone()}, + ClangBackEnd::ClangQueryGatherer gatherer{&filePathCache, {source.clone()}, {unsaved.clone()}, query.clone()}; + ClangBackEnd::ClangQueryGatherer manyGatherer{&filePathCache, + {source.clone(), source.clone(), source.clone()}, {unsaved.clone()}, query.clone()}; }; TEST_F(ClangQueryGatherer, CreateSourceRangesAndDiagnostics) { - auto sourceRangesAndDiagnostics = gatherer.createSourceRangesAndDiagnosticsForSource(source.clone(), {}, query.clone()); + auto sourceRangesAndDiagnostics = gatherer.createSourceRangesAndDiagnosticsForSource(&filePathCache, source.clone(), {}, query.clone()); ASSERT_THAT(sourceRangesAndDiagnostics, Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, @@ -98,7 +100,7 @@ TEST_F(ClangQueryGatherer, CreateSourceRangesAndDiagnostics) TEST_F(ClangQueryGatherer, CreateSourceRangesAndDiagnosticssWithUnsavedContent) { - auto sourceRangesAndDiagnostics = gatherer.createSourceRangesAndDiagnosticsForSource(source.clone(), {unsaved}, query.clone()); + auto sourceRangesAndDiagnostics = gatherer.createSourceRangesAndDiagnosticsForSource(&filePathCache, source.clone(), {unsaved}, query.clone()); ASSERT_THAT(sourceRangesAndDiagnostics, Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, @@ -113,7 +115,7 @@ TEST_F(ClangQueryGatherer, CanCreateSourceRangesAndDiagnosticsIfItHasSources) TEST_F(ClangQueryGatherer, CanNotCreateSourceRangesAndDiagnosticsIfItHasNoSources) { - ClangBackEnd::ClangQueryGatherer empthyGatherer{{}, {unsaved.clone()}, query.clone()}; + ClangBackEnd::ClangQueryGatherer empthyGatherer{&filePathCache, {}, {unsaved.clone()}, query.clone()}; ASSERT_FALSE(empthyGatherer.canCreateSourceRangesAndDiagnostics()); } diff --git a/tests/unit/unittest/filepath-test.cpp b/tests/unit/unittest/filepath-test.cpp new file mode 100644 index 0000000000..d82e94f211 --- /dev/null +++ b/tests/unit/unittest/filepath-test.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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. +** +****************************************************************************/ + +#include "googletest.h" + +#include <filepath.h> + +namespace { + +TEST(FilePath, CreateFromPathString) +{ + ClangBackEnd::FilePath filePath{Utils::PathString{"/file/pathOne"}}; + + ASSERT_THAT(filePath.directory(), "/file"); + ASSERT_THAT(filePath.name(), "pathOne"); +} + +TEST(FilePath, CreateFromQString) +{ + ClangBackEnd::FilePath filePath{QString{"/file/pathOne"}}; + + ASSERT_THAT(filePath.directory(), "/file"); + ASSERT_THAT(filePath.name(), "pathOne"); +} + +TEST(FilePath, EmptyFilePath) +{ + ClangBackEnd::FilePath filePath; + + ASSERT_THAT(filePath.directory(), ""); + ASSERT_THAT(filePath.name(), ""); +} + +} diff --git a/tests/unit/unittest/pchcreator-test.cpp b/tests/unit/unittest/pchcreator-test.cpp index 0798e9d63c..763521da42 100644 --- a/tests/unit/unittest/pchcreator-test.cpp +++ b/tests/unit/unittest/pchcreator-test.cpp @@ -73,7 +73,7 @@ protected: PathString main2Path = TESTDATA_DIR "/includecollector_main2.cpp"; PathString header1Path = TESTDATA_DIR "/includecollector_header1.h"; PathString header2Path = TESTDATA_DIR "/includecollector_header2.h"; - SmallString generatedFileName = "includecollector_generated_file.h"; + PathString generatedFileName = "includecollector_generated_file.h"; PathString generatedFilePath = TESTDATA_DIR "/includecollector_generated_file.h"; ProjectPartContainer projectPart1{"project1", {"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"}, diff --git a/tests/unit/unittest/sourcerangeextractor-test.cpp b/tests/unit/unittest/sourcerangeextractor-test.cpp index df527b4e62..8bf676b796 100644 --- a/tests/unit/unittest/sourcerangeextractor-test.cpp +++ b/tests/unit/unittest/sourcerangeextractor-test.cpp @@ -28,23 +28,12 @@ #include <sourcerangeextractor.h> #include <sourcerangescontainer.h> - -#if defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-parameter" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning( disable : 4100 ) -#endif +#include <stringcache.h> #include <clang/Basic/SourceManager.h> #include <clang/Lex/Lexer.h> -#if defined(__GNUC__) -# pragma GCC diagnostic pop -#elif defined(_MSC_VER) -# pragma warning(pop) -#endif +#include <mutex> using testing::Contains; using ::testing::Eq; @@ -65,7 +54,8 @@ protected: TestClangTool clangTool{TESTDATA_DIR, "sourcerangeextractor_location.cpp", "", {"cc", "sourcerangeextractor_location.cpp"}}; ClangBackEnd::SourceRangesContainer sourceRangesContainer; const clang::SourceManager &sourceManager{clangTool.sourceManager()}; - ClangBackEnd::SourceRangeExtractor extractor{sourceManager, clangTool.languageOptions(), sourceRangesContainer}; + ClangBackEnd::StringCache<Utils::PathString, std::mutex> filePathCache; + ClangBackEnd::SourceRangeExtractor extractor{sourceManager, clangTool.languageOptions(), filePathCache, sourceRangesContainer}; clang::SourceLocation startLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID()); clang::SourceLocation endLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID()).getLocWithOffset(4); clang::SourceRange sourceRange{startLocation, endLocation}; @@ -76,7 +66,7 @@ using SourceRangeExtractorSlowTest = SourceRangeExtractor; TEST_F(SourceRangeExtractorSlowTest, ExtractSourceRangeContainer) { - SourceRangeWithTextContainer sourceRangeContainer{1, 1, 1, 0, 1, 10, 9, Utils::SmallString("int value;")}; + SourceRangeWithTextContainer sourceRangeContainer{0, 1, 1, 0, 1, 10, 9, Utils::SmallString("int value;")}; extractor.addSourceRange(sourceRange); diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index 73e0ed31a3..4e32ce0413 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -63,6 +63,8 @@ SOURCES += \ projectupdater-test.cpp \ pchmanagerserver-test.cpp \ pchmanagerclientserverinprocess-test.cpp \ + clangquerygatherer-test.cpp \ + filepath-test.cpp !isEmpty(LIBCLANG_LIBS) { SOURCES += \ |