Clang: Make file ids unique

Clang file ids are only unique for one query. Because we query in parallel
we have to manage our own unique ids.

Change-Id: I67d57d8b1766cab75ad252a14e57bbf9dc5fdb79
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Tim Jenssen
2017-07-03 11:12:00 +02:00
parent 35ca318d18
commit dae4477cd3
27 changed files with 231 additions and 159 deletions

View File

@@ -155,6 +155,7 @@ HEADERS += \
$$PWD/pchmanagerclientproxy.h \ $$PWD/pchmanagerclientproxy.h \
$$PWD/projectpartpch.h \ $$PWD/projectpartpch.h \
$$PWD/precompiledheadersupdatedmessage.h \ $$PWD/precompiledheadersupdatedmessage.h \
$$PWD/stringcache.h \
$$PWD/removepchprojectpartsmessage.h \ $$PWD/removepchprojectpartsmessage.h \
$$PWD/clangcodemodelclientmessages.h \ $$PWD/clangcodemodelclientmessages.h \
$$PWD/clangcodemodelservermessages.h \ $$PWD/clangcodemodelservermessages.h \

View File

@@ -37,66 +37,62 @@ class FilePath
{ {
public: public:
FilePath() = default; 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(); auto found = foundReverse.base();
--found;
Utils::SmallString fileName(found, filePath.end()); m_slashIndex = std::size_t(std::distance(m_path.begin(), found));
if (foundReverse != filePath.rend()) }
filePath.resize(std::size_t(std::distance(filePath.begin(), --found)));
directory_ = std::move(filePath); explicit FilePath(const Utils::PathString &filePath)
name_ = std::move(fileName); : FilePath(filePath.clone())
{
}
explicit FilePath(Utils::PathString &&filePath, std::size_t slashIndex)
: m_path(std::move(filePath)),
m_slashIndex(slashIndex)
{
} }
explicit FilePath(const QString &filePath) explicit FilePath(const QString &filePath)
: FilePath(Utils::SmallString(filePath)) : FilePath(Utils::PathString(filePath))
{ {
} }
FilePath(Utils::SmallString &&directory, Utils::SmallString &&name) FilePath(const Utils::PathString &directory, const Utils::PathString &name)
: directory_(std::move(directory)), : m_path({std::move(directory), "/", std::move(name)}),
name_(std::move(name)) m_slashIndex(directory.size())
{} {}
const Utils::SmallString &directory() const Utils::SmallStringView directory() const
{ {
return directory_; return m_path.mid(0, m_slashIndex);
} }
Utils::SmallString takeDirectory() Utils::SmallStringView name() const
{ {
return std::move(directory_); return m_path.mid(m_slashIndex + 1, m_path.size() - m_slashIndex - 1);
} }
const Utils::SmallString &name() const const Utils::PathString &path() const
{ {
return name_; return m_path;
}
Utils::SmallString takeName()
{
return std::move(name_);
}
Utils::PathString path() const
{
return {directory_, "/", name_};
} }
friend QDataStream &operator<<(QDataStream &out, const FilePath &filePath) friend QDataStream &operator<<(QDataStream &out, const FilePath &filePath)
{ {
out << filePath.directory_; out << filePath.m_path;
out << filePath.name_;
return out; return out;
} }
friend QDataStream &operator>>(QDataStream &in, FilePath &filePath) friend QDataStream &operator>>(QDataStream &in, FilePath &filePath)
{ {
in >> filePath.directory_; in >> filePath.m_path;
in >> filePath.name_;
return in; return in;
} }
@@ -110,24 +106,22 @@ public:
friend bool operator==(const FilePath &first, const FilePath &second) friend bool operator==(const FilePath &first, const FilePath &second)
{ {
return first.name_ == second.name_ return first.m_path == second.m_path;
&& first.directory_ == second.directory_;
} }
friend bool operator<(const FilePath &first, const FilePath &second) friend bool operator<(const FilePath &first, const FilePath &second)
{ {
return std::tie(first.name_, first.directory_) return first.m_path < second.m_path;
< std::tie(second.name_, second.directory_);
} }
FilePath clone() const FilePath clone() const
{ {
return FilePath(directory_.clone(), name_.clone()); return FilePath(m_path.clone(), m_slashIndex);
} }
private: private:
Utils::SmallString directory_; Utils::PathString m_path = "/";
Utils::SmallString name_; std::size_t m_slashIndex = 0;
}; };
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const FilePath &filePath); CMBIPC_EXPORT QDebug operator<<(QDebug debug, const FilePath &filePath);

View File

@@ -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()) { if (m_filePathHash.find(fileId) == m_filePathHash.end())
m_filePathHash.emplace(std::piecewise_construct, m_filePathHash.emplace(fileId, std::move(filePath));
std::forward_as_tuple(fileId),
std::forward_as_tuple(std::move(fileDirectory), std::move(fileName)));
}
} }
void reserve(std::size_t size) void reserve(std::size_t size)

View File

@@ -46,10 +46,10 @@ QDebug operator<<(QDebug debug, const SourceLocationContainer &container)
std::ostream &operator<<(std::ostream &os, const SourceLocationContainer &container) std::ostream &operator<<(std::ostream &os, const SourceLocationContainer &container)
{ {
os << "(" os << "("
<< container.fileHash() << ", "
<< container.line() << ", " << container.line() << ", "
<< container.column() << ", " << container.column() << ", "
<< container.offset() << ", " << container.offset()
<< container.fileHash()
<< ")"; << ")";
return os; return os;

View File

@@ -110,6 +110,8 @@ private:
Utils::SmallString m_text; Utils::SmallString m_text;
}; };
using SourceRangeWithTextContainers = std::vector<SourceRangeWithTextContainer>;
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const SourceRangeWithTextContainer &container); CMBIPC_EXPORT QDebug operator<<(QDebug debug, const SourceRangeWithTextContainer &container);
std::ostream &operator<<(std::ostream &os, const SourceRangeWithTextContainer &container); std::ostream &operator<<(std::ostream &os, const SourceRangeWithTextContainer &container);
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -25,16 +25,26 @@
#pragma once #pragma once
#include "clangpchmanagerbackend_global.h"
#include <utils/smallstringview.h> #include <utils/smallstringview.h>
#include <algorithm> #include <algorithm>
#include <mutex>
#include <vector> #include <vector>
namespace ClangBackEnd { 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 StringCache
{ {
class StringCacheEntry class StringCacheEntry
@@ -79,6 +89,8 @@ public:
uint stringId(Utils::SmallStringView stringView) uint stringId(Utils::SmallStringView stringView)
{ {
std::lock_guard<Mutex> lock(m_mutex);
Found found = find(stringView); Found found = find(stringView);
if (!found.wasFound) if (!found.wasFound)
@@ -89,6 +101,8 @@ public:
std::vector<uint> stringIds(const std::vector<StringType> &strings) std::vector<uint> stringIds(const std::vector<StringType> &strings)
{ {
std::lock_guard<Mutex> lock(m_mutex);
std::vector<uint> ids; std::vector<uint> ids;
ids.reserve(strings.size()); ids.reserve(strings.size());
@@ -102,11 +116,15 @@ public:
const StringType &string(uint id) const const StringType &string(uint id) const
{ {
std::lock_guard<Mutex> lock(m_mutex);
return m_strings.at(m_indices.at(id)).string; return m_strings.at(m_indices.at(id)).string;
} }
std::vector<StringType> strings(const std::vector<uint> &ids) const std::vector<StringType> strings(const std::vector<uint> &ids) const
{ {
std::lock_guard<Mutex> lock(m_mutex);
std::vector<StringType> strings; std::vector<StringType> strings;
strings.reserve(ids.size()); strings.reserve(ids.size());
@@ -155,6 +173,7 @@ private:
private: private:
StringCacheEntries m_strings; StringCacheEntries m_strings;
std::vector<uint> m_indices; std::vector<uint> m_indices;
mutable Mutex m_mutex;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -68,8 +68,8 @@ QDataStream &operator>>(QDataStream &in, BasicSmallString<Size> &string)
return in; return in;
} }
inline template <typename String>
QDebug &operator<<(QDebug &debug, const SmallString &string) QDebug &operator<<(QDebug &debug, const String &string)
{ {
using QT_PREPEND_NAMESPACE(operator<<); using QT_PREPEND_NAMESPACE(operator<<);

View File

@@ -104,6 +104,11 @@ public:
return const_reverse_iterator(begin() - static_cast<std::size_t>(1)); return const_reverse_iterator(begin() - static_cast<std::size_t>(1));
} }
operator std::string() const
{
return std::string(data(), size());
}
private: private:
const char *m_pointer; const char *m_pointer;
size_type m_size; size_type m_size;

View File

@@ -104,19 +104,6 @@ void RefactoringClient::setRefactoringConnectionClient(
this->connectionClient = connectionClient; 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( std::unordered_map<uint, QString> RefactoringClient::convertFilePaths(
const ClangBackEnd::FilePathDict &filePaths) const ClangBackEnd::FilePathDict &filePaths)
{ {
@@ -126,7 +113,7 @@ std::unordered_map<uint, QString> RefactoringClient::convertFilePaths(
auto convertFilePath = [] (const ClangBackEnd::FilePathDict::value_type &dictonaryEntry) { auto convertFilePath = [] (const ClangBackEnd::FilePathDict::value_type &dictonaryEntry) {
return std::make_pair(dictonaryEntry.first, return std::make_pair(dictonaryEntry.first,
concatenateFilePath(dictonaryEntry.second).toQString()); dictonaryEntry.second.path().toQString());
}; };
std::transform(filePaths.begin(), std::transform(filePaths.begin(),

View File

@@ -19,7 +19,6 @@ HEADERS += \
$$PWD/environment.h \ $$PWD/environment.h \
$$PWD/clangpathwatcher.h \ $$PWD/clangpathwatcher.h \
$$PWD/projectparts.h \ $$PWD/projectparts.h \
$$PWD/stringcache.h \
$$PWD/idpaths.h \ $$PWD/idpaths.h \
$$PWD/pchcreatorinterface.h \ $$PWD/pchcreatorinterface.h \
$$PWD/clangpathwatcherinterface.h \ $$PWD/clangpathwatcherinterface.h \

View File

@@ -30,27 +30,15 @@
#include <sourcerangescontainer.h> #include <sourcerangescontainer.h>
#include <QTime> #include <stringcache.h>
#if defined(__GNUC__) #include <QTime>
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-parameter"
#elif defined(_MSC_VER)
# pragma warning(push)
# pragma warning( disable : 4100 )
#endif
#include <clang/ASTMatchers/ASTMatchers.h> #include <clang/ASTMatchers/ASTMatchers.h>
#include <clang/ASTMatchers/ASTMatchFinder.h> #include <clang/ASTMatchers/ASTMatchFinder.h>
#include <clang/ASTMatchers/Dynamic/Diagnostics.h> #include <clang/ASTMatchers/Dynamic/Diagnostics.h>
#include <clang/ASTMatchers/Dynamic/Parser.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::Diagnostics;
using clang::ast_matchers::dynamic::Parser; using clang::ast_matchers::dynamic::Parser;
using clang::ast_matchers::BoundNodes; using clang::ast_matchers::BoundNodes;
@@ -66,8 +54,10 @@ struct CollectBoundNodes : MatchFinder::MatchCallback {
} }
}; };
ClangQuery::ClangQuery(Utils::SmallString &&query) ClangQuery::ClangQuery(StringCache<Utils::PathString, std::mutex> &filePathCache,
: query(std::move(query)) Utils::SmallString &&query)
: query(std::move(query)),
filePathCache(filePathCache)
{ {
} }
@@ -226,6 +216,7 @@ void ClangQuery::matchLocation(
SourceRangeExtractor extractor(ast->getSourceManager(), SourceRangeExtractor extractor(ast->getSourceManager(),
ast->getLangOpts(), ast->getLangOpts(),
filePathCache,
sourceRangesContainer); sourceRangesContainer);
extractor.addSourceRanges(sourceRanges); extractor.addSourceRanges(sourceRanges);

View File

@@ -30,6 +30,8 @@
#include <sourcerangescontainer.h> #include <sourcerangescontainer.h>
#include <dynamicastmatcherdiagnosticcontainer.h> #include <dynamicastmatcherdiagnosticcontainer.h>
#include <stringcache.h>
namespace clang { namespace clang {
namespace ast_matchers { namespace ast_matchers {
namespace dynamic { namespace dynamic {
@@ -49,7 +51,7 @@ namespace ClangBackEnd {
class ClangQuery : public ClangTool class ClangQuery : public ClangTool
{ {
public: public:
ClangQuery(Utils::SmallString &&query={}); ClangQuery(StringCache<Utils::PathString, std::mutex> &filePathCache, Utils::SmallString &&query={});
void setQuery(Utils::SmallString &&query); void setQuery(Utils::SmallString &&query);
@@ -67,6 +69,7 @@ private:
SourceRangesContainer sourceRangesContainer; SourceRangesContainer sourceRangesContainer;
Utils::SmallString query; Utils::SmallString query;
std::vector<DynamicASTMatcherDiagnosticContainer> diagnosticContainers_; std::vector<DynamicASTMatcherDiagnosticContainer> diagnosticContainers_;
StringCache<Utils::PathString, std::mutex> &filePathCache;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -29,10 +29,12 @@
namespace ClangBackEnd { 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, std::vector<V2::FileContainer> &&unsaved,
Utils::SmallString &&query) Utils::SmallString &&query)
: m_sources(std::move(sources)), : m_filePathCache(filePathCache),
m_sources(std::move(sources)),
m_unsaved(std::move(unsaved)), m_unsaved(std::move(unsaved)),
m_query(std::move(query)) m_query(std::move(query))
{ {
@@ -40,11 +42,12 @@ ClangQueryGatherer::ClangQueryGatherer(std::vector<V2::FileContainer> &&sources,
SourceRangesAndDiagnosticsForQueryMessage SourceRangesAndDiagnosticsForQueryMessage
ClangQueryGatherer::createSourceRangesAndDiagnosticsForSource( ClangQueryGatherer::createSourceRangesAndDiagnosticsForSource(
StringCache<Utils::PathString, std::mutex> *filePathCache,
V2::FileContainer &&source, V2::FileContainer &&source,
const std::vector<V2::FileContainer> &unsaved, const std::vector<V2::FileContainer> &unsaved,
Utils::SmallString &&query) Utils::SmallString &&query)
{ {
ClangQuery clangQuery(std::move(query)); ClangQuery clangQuery(*filePathCache, std::move(query));
clangQuery.addFile(source.filePath().directory(), clangQuery.addFile(source.filePath().directory(),
source.filePath().name(), source.filePath().name(),
@@ -65,7 +68,8 @@ bool ClangQueryGatherer::canCreateSourceRangesAndDiagnostics() const
SourceRangesAndDiagnosticsForQueryMessage ClangQueryGatherer::createNextSourceRangesAndDiagnostics() SourceRangesAndDiagnosticsForQueryMessage ClangQueryGatherer::createNextSourceRangesAndDiagnostics()
{ {
auto message = createSourceRangesAndDiagnosticsForSource(std::move(m_sources.back()), auto message = createSourceRangesAndDiagnosticsForSource(m_filePathCache,
std::move(m_sources.back()),
m_unsaved, m_unsaved,
m_query.clone()); m_query.clone());
m_sources.pop_back(); m_sources.pop_back();
@@ -77,6 +81,7 @@ ClangQueryGatherer::Future ClangQueryGatherer::startCreateNextSourceRangesAndDia
{ {
Future future = std::async(std::launch::async, Future future = std::async(std::launch::async,
createSourceRangesAndDiagnosticsForSource, createSourceRangesAndDiagnosticsForSource,
m_filePathCache,
std::move(m_sources.back()), std::move(m_sources.back()),
m_unsaved, m_unsaved,
m_query.clone()); m_query.clone());

View File

@@ -27,6 +27,7 @@
#include <sourcerangesanddiagnosticsforquerymessage.h> #include <sourcerangesanddiagnosticsforquerymessage.h>
#include <filecontainerv2.h> #include <filecontainerv2.h>
#include <stringcache.h>
#include <future> #include <future>
@@ -38,16 +39,16 @@ public:
using Future = std::future<SourceRangesAndDiagnosticsForQueryMessage>; using Future = std::future<SourceRangesAndDiagnosticsForQueryMessage>;
ClangQueryGatherer() = default; 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, std::vector<V2::FileContainer> &&unsaved,
Utils::SmallString &&query); Utils::SmallString &&query);
static static SourceRangesAndDiagnosticsForQueryMessage createSourceRangesAndDiagnosticsForSource(
SourceRangesAndDiagnosticsForQueryMessage createSourceRangesAndDiagnosticsForSource( StringCache<Utils::PathString, std::mutex> *filePathCache,
V2::FileContainer &&source, V2::FileContainer &&source,
const std::vector<V2::FileContainer> &unsaved, const std::vector<V2::FileContainer> &unsaved,
Utils::SmallString &&query); Utils::SmallString &&query);
bool canCreateSourceRangesAndDiagnostics() const; bool canCreateSourceRangesAndDiagnostics() const;
SourceRangesAndDiagnosticsForQueryMessage createNextSourceRangesAndDiagnostics(); SourceRangesAndDiagnosticsForQueryMessage createNextSourceRangesAndDiagnostics();
Future startCreateNextSourceRangesAndDiagnosticsMessage(); Future startCreateNextSourceRangesAndDiagnosticsMessage();
@@ -66,6 +67,7 @@ protected:
std::vector<Future> finishedFutures(); std::vector<Future> finishedFutures();
private: private:
StringCache<Utils::PathString, std::mutex> *m_filePathCache = nullptr;
std::vector<V2::FileContainer> m_sources; std::vector<V2::FileContainer> m_sources;
std::vector<V2::FileContainer> m_unsaved; std::vector<V2::FileContainer> m_unsaved;
Utils::SmallString m_query; Utils::SmallString m_query;

View File

@@ -84,23 +84,12 @@ template
void ClangTool::addFiles<Utils::PathStringVector>(const Utils::PathStringVector &filePaths, void ClangTool::addFiles<Utils::PathStringVector>(const Utils::PathStringVector &filePaths,
const Utils::SmallStringVector &arguments); 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) void ClangTool::addUnsavedFiles(const V2::FileContainers &unsavedFiles)
{ {
unsavedFileContents.reserve(unsavedFileContents.size() + unsavedFiles.size()); unsavedFileContents.reserve(unsavedFileContents.size() + unsavedFiles.size());
auto convertToUnsavedFileContent = [] (const V2::FileContainer &unsavedFile) { auto convertToUnsavedFileContent = [] (const V2::FileContainer &unsavedFile) {
return UnsavedFileContent{toNativeFilePath(unsavedFile.filePath()), return UnsavedFileContent{toNativePath(unsavedFile.filePath().path().clone()),
unsavedFile.unsavedFileContent().clone()}; unsavedFile.unsavedFileContent().clone()};
}; };
@@ -111,7 +100,8 @@ void ClangTool::addUnsavedFiles(const V2::FileContainers &unsavedFiles)
} }
namespace { namespace {
llvm::StringRef toStringRef(const Utils::SmallString &string) template <typename String>
llvm::StringRef toStringRef(const String &string)
{ {
return llvm::StringRef(string.data(), string.size()); return llvm::StringRef(string.data(), string.size());
} }

View File

@@ -77,13 +77,13 @@ struct FileContent
struct UnsavedFileContent struct UnsavedFileContent
{ {
UnsavedFileContent(Utils::SmallString &&filePath, UnsavedFileContent(Utils::PathString &&filePath,
Utils::SmallString &&content) Utils::SmallString &&content)
: filePath(std::move(filePath)), : filePath(std::move(filePath)),
content(std::move(content)) content(std::move(content))
{} {}
Utils::SmallString filePath; Utils::PathString filePath;
Utils::SmallString content; Utils::SmallString content;
}; };

View File

@@ -37,6 +37,7 @@
#include <QCoreApplication> #include <QCoreApplication>
#include <functional> #include <functional>
#include <atomic>
namespace ClangBackEnd { namespace ClangBackEnd {
@@ -125,7 +126,7 @@ void RefactoringServer::gatherSourceRangesAndDiagnosticsForQueryMessages(
uint freeProcessors = std::thread::hardware_concurrency(); uint freeProcessors = std::thread::hardware_concurrency();
#endif #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_gatherer.setProcessingSlotCount(freeProcessors);
m_pollTimer.start(); m_pollTimer.start();

View File

@@ -30,7 +30,12 @@
#include <refactoringserverinterface.h> #include <refactoringserverinterface.h>
#include <QTimer> #include <QTimer>
#include <stringcache.h>
#include <utils/smallstring.h>
#include <future>
#include <mutex>
#include <vector> #include <vector>
namespace ClangBackEnd { namespace ClangBackEnd {
@@ -65,6 +70,7 @@ private:
Utils::SmallString &&query); Utils::SmallString &&query);
private: private:
StringCache<Utils::PathString, std::mutex> m_filePathCache;
ClangQueryGatherer m_gatherer; ClangQueryGatherer m_gatherer;
QTimer m_pollTimer; QTimer m_pollTimer;
}; };

View File

@@ -53,7 +53,7 @@
namespace ClangBackEnd { namespace ClangBackEnd {
inline inline
llvm::SmallString<256> absolutePath(const llvm::StringRef &path) llvm::SmallString<256> absolutePath(clang::StringRef path)
{ {
llvm::SmallString<256> absolutePath(path); llvm::SmallString<256> absolutePath(path);
@@ -64,9 +64,9 @@ llvm::SmallString<256> absolutePath(const llvm::StringRef &path)
} }
template <typename Container> 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 #ifdef _WIN32
std::replace(path.begin(), path.end(), '\\', '/'); std::replace(path.begin(), path.end(), '\\', '/');
@@ -89,13 +89,9 @@ void appendSourceLocationsToSourceLocationsContainer(
const auto fileId = decomposedLoction.first; const auto fileId = decomposedLoction.first;
const auto offset = decomposedLoction.second; const auto offset = decomposedLoction.second;
const auto fileEntry = sourceManager.getFileEntryForID(fileId); 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(), sourceLocationsContainer.insertFilePath(fileId.getHashValue(),
fromNativePath(filePath), fromNativePath(fileEntry->tryGetRealPathName()));
fromNativePath(fileName));
sourceLocationsContainer.insertSourceLocation(fileId.getHashValue(), sourceLocationsContainer.insertSourceLocation(fileId.getHashValue(),
fullSourceLocation.getSpellingLineNumber(), fullSourceLocation.getSpellingLineNumber(),
fullSourceLocation.getSpellingColumnNumber(), fullSourceLocation.getSpellingColumnNumber(),

View File

@@ -51,11 +51,14 @@
namespace ClangBackEnd { namespace ClangBackEnd {
SourceRangeExtractor::SourceRangeExtractor(const clang::SourceManager &sourceManager, SourceRangeExtractor::SourceRangeExtractor(
const clang::SourceManager &sourceManager,
const clang::LangOptions &languageOptions, const clang::LangOptions &languageOptions,
ClangBackEnd::StringCache<Utils::PathString, std::mutex> &filePathCache,
SourceRangesContainer &sourceRangesContainer) SourceRangesContainer &sourceRangesContainer)
: sourceManager(sourceManager), : sourceManager(sourceManager),
languageOptions(languageOptions), languageOptions(languageOptions),
filePathCache(filePathCache),
sourceRangesContainer(sourceRangesContainer) sourceRangesContainer(sourceRangesContainer)
{ {
} }
@@ -123,19 +126,16 @@ const clang::SourceRange SourceRangeExtractor::extendSourceRangeToLastTokenEnd(c
return {sourceRange.getBegin(), endLocation}; return {sourceRange.getBegin(), endLocation};
} }
void SourceRangeExtractor::insertSourceRange(uint fileHash, void SourceRangeExtractor::insertSourceRange(uint fileId,
Utils::SmallString &&directoryPath, Utils::PathString &&filePath,
Utils::SmallString &&fileName,
const clang::FullSourceLoc &startLocation, const clang::FullSourceLoc &startLocation,
uint startOffset, uint startOffset,
const clang::FullSourceLoc &endLocation, const clang::FullSourceLoc &endLocation,
uint endOffset, uint endOffset,
Utils::SmallString &&lineSnippet) Utils::SmallString &&lineSnippet)
{ {
sourceRangesContainer.insertFilePath(fileHash, sourceRangesContainer.insertFilePath(fileId, std::move(filePath));
std::move(directoryPath), sourceRangesContainer.insertSourceRange(fileId,
std::move(fileName));
sourceRangesContainer.insertSourceRange(fileHash,
startLocation.getSpellingLineNumber(), startLocation.getSpellingLineNumber(),
startLocation.getSpellingColumnNumber(), startLocation.getSpellingColumnNumber(),
startOffset, startOffset,
@@ -145,6 +145,17 @@ void SourceRangeExtractor::insertSourceRange(uint fileHash,
std::move(lineSnippet)); 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) void SourceRangeExtractor::addSourceRange(const clang::SourceRange &sourceRange)
{ {
auto extendedSourceRange = extendSourceRangeToLastTokenEnd(sourceRange); auto extendedSourceRange = extendSourceRangeToLastTokenEnd(sourceRange);
@@ -158,15 +169,13 @@ void SourceRangeExtractor::addSourceRange(const clang::SourceRange &sourceRange)
const auto startOffset = startDecomposedLoction.second; const auto startOffset = startDecomposedLoction.second;
const auto endOffset = endDecomposedLoction.second; const auto endOffset = endDecomposedLoction.second;
const auto fileEntry = sourceManager.getFileEntryForID(fileId); 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(), Utils::SmallString lineSnippet = getExpandedText(startSourceLocation.getBufferData(),
startOffset, startOffset,
endOffset); endOffset);
insertSourceRange(fileId.getHashValue(),
fromNativePath(filePath), insertSourceRange(findFileId(fileId, fileEntry),
{fileName.data(), fileName.size()}, fromNativePath(fileEntry->tryGetRealPathName()),
startSourceLocation, startSourceLocation,
startOffset, startOffset,
endSourceLocation, endSourceLocation,

View File

@@ -25,9 +25,14 @@
#pragma once #pragma once
#include <stringcache.h>
#include <filepath.h>
#include <utils/smallstringfwd.h> #include <utils/smallstringfwd.h>
#include <vector> #include <vector>
#include <unordered_map>
using uint = unsigned int; using uint = unsigned int;
@@ -40,6 +45,8 @@ class SourceManager;
class LangOptions; class LangOptions;
class SourceRange; class SourceRange;
class FullSourceLoc; class FullSourceLoc;
class FileID;
class FileEntry;
} }
namespace ClangBackEnd { namespace ClangBackEnd {
@@ -52,6 +59,7 @@ class SourceRangeExtractor
public: public:
SourceRangeExtractor(const clang::SourceManager &sourceManager, SourceRangeExtractor(const clang::SourceManager &sourceManager,
const clang::LangOptions &languageOptions, const clang::LangOptions &languageOptions,
ClangBackEnd::StringCache<Utils::PathString, std::mutex> &filePathCache,
SourceRangesContainer &sourceRangesContainer); SourceRangesContainer &sourceRangesContainer);
void addSourceRange(const clang::SourceRange &sourceRange); void addSourceRange(const clang::SourceRange &sourceRange);
@@ -66,18 +74,21 @@ public:
const clang::SourceRange extendSourceRangeToLastTokenEnd(const clang::SourceRange sourceRange); const clang::SourceRange extendSourceRangeToLastTokenEnd(const clang::SourceRange sourceRange);
private: private:
void insertSourceRange(uint fileHash, void insertSourceRange(uint fileId,
Utils::SmallString &&directoryPath, Utils::PathString &&filePath,
Utils::SmallString &&fileName,
const clang::FullSourceLoc &startLocation, const clang::FullSourceLoc &startLocation,
uint startOffset, uint startOffset,
const clang::FullSourceLoc &endLocation, const clang::FullSourceLoc &endLocation,
uint endOffset, uint endOffset,
Utils::SmallString &&lineSnippet); Utils::SmallString &&lineSnippet);
uint findFileId(clang::FileID fileId, const clang::FileEntry *fileEntry) const;
private: private:
mutable std::unordered_map<uint, uint> m_fileIdMapping;
const clang::SourceManager &sourceManager; const clang::SourceManager &sourceManager;
const clang::LangOptions &languageOptions; const clang::LangOptions &languageOptions;
ClangBackEnd::StringCache<Utils::PathString, std::mutex> &filePathCache;
SourceRangesContainer &sourceRangesContainer; SourceRangesContainer &sourceRangesContainer;
}; };

View File

@@ -29,7 +29,10 @@
#include <clangquery.h> #include <clangquery.h>
#include <mutex>
using ClangBackEnd::ClangQuery; using ClangBackEnd::ClangQuery;
using ClangBackEnd::StringCache;
using testing::IsEmpty; using testing::IsEmpty;
using testing::Not; using testing::Not;
@@ -43,8 +46,9 @@ protected:
void SetUp() override; void SetUp() override;
protected: protected:
::ClangQuery simpleFunctionQuery; StringCache<Utils::PathString, std::mutex> filePathCache;
::ClangQuery simpleClassQuery; ::ClangQuery simpleFunctionQuery{filePathCache};
::ClangQuery simpleClassQuery{filePathCache};
}; };
using ClangQuerySlowTest = ClangQuery; using ClangQuerySlowTest = ClangQuery;
@@ -77,7 +81,7 @@ TEST_F(ClangQuerySlowTest, RootSourceRangeForSimpleFunctionDeclarationRange)
TEST_F(ClangQuerySlowTest, SourceRangeInUnsavedFileDeclarationRange) 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.addFile(TESTDATA_DIR, "query_simplefunction.cpp", "#include \"unsaved.h\"", {"cc", "query_simplefunction.cpp", "-std=c++14"});
query.setQuery("functionDecl()"); query.setQuery("functionDecl()");
ClangBackEnd::V2::FileContainer unsavedFile{{TESTDATA_DIR, "unsaved.h"}, "void unsaved();", {}}; 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 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.addFile(TESTDATA_DIR, "query_simplefunction.cpp", "void f() {}", {"cc", "query_simplefunction.cpp", "-std=c++14"});
query.setQuery("functionDecl()"); query.setQuery("functionDecl()");
ClangBackEnd::V2::FileContainer unsavedFile{{TESTDATA_DIR, "query_simplefunction.cpp"}, "void unsaved();", {}}; ClangBackEnd::V2::FileContainer unsavedFile{{TESTDATA_DIR, "query_simplefunction.cpp"}, "void unsaved();", {}};

View File

@@ -71,6 +71,7 @@ protected:
void SetUp() override; void SetUp() override;
protected: protected:
ClangBackEnd::StringCache<Utils::PathString, std::mutex> filePathCache;
Utils::SmallString sourceContent{"#include \"query_simplefunction.h\"\nvoid f()\n {}"}; Utils::SmallString sourceContent{"#include \"query_simplefunction.h\"\nvoid f()\n {}"};
FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"}, FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"},
sourceContent.clone(), sourceContent.clone(),
@@ -80,15 +81,16 @@ protected:
unsavedContent.clone(), unsavedContent.clone(),
{}}; {}};
Utils::SmallString query{"functionDecl()"}; Utils::SmallString query{"functionDecl()"};
ClangBackEnd::ClangQueryGatherer gatherer{{source.clone()}, {unsaved.clone()}, query.clone()}; ClangBackEnd::ClangQueryGatherer gatherer{&filePathCache, {source.clone()}, {unsaved.clone()}, query.clone()};
ClangBackEnd::ClangQueryGatherer manyGatherer{{source.clone(), source.clone(), source.clone()}, ClangBackEnd::ClangQueryGatherer manyGatherer{&filePathCache,
{source.clone(), source.clone(), source.clone()},
{unsaved.clone()}, {unsaved.clone()},
query.clone()}; query.clone()};
}; };
TEST_F(ClangQueryGatherer, CreateSourceRangesAndDiagnostics) TEST_F(ClangQueryGatherer, CreateSourceRangesAndDiagnostics)
{ {
auto sourceRangesAndDiagnostics = gatherer.createSourceRangesAndDiagnosticsForSource(source.clone(), {}, query.clone()); auto sourceRangesAndDiagnostics = gatherer.createSourceRangesAndDiagnosticsForSource(&filePathCache, source.clone(), {}, query.clone());
ASSERT_THAT(sourceRangesAndDiagnostics, ASSERT_THAT(sourceRangesAndDiagnostics,
Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges,
@@ -98,7 +100,7 @@ TEST_F(ClangQueryGatherer, CreateSourceRangesAndDiagnostics)
TEST_F(ClangQueryGatherer, CreateSourceRangesAndDiagnosticssWithUnsavedContent) 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, ASSERT_THAT(sourceRangesAndDiagnostics,
Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges, Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges,
@@ -113,7 +115,7 @@ TEST_F(ClangQueryGatherer, CanCreateSourceRangesAndDiagnosticsIfItHasSources)
TEST_F(ClangQueryGatherer, CanNotCreateSourceRangesAndDiagnosticsIfItHasNoSources) TEST_F(ClangQueryGatherer, CanNotCreateSourceRangesAndDiagnosticsIfItHasNoSources)
{ {
ClangBackEnd::ClangQueryGatherer empthyGatherer{{}, {unsaved.clone()}, query.clone()}; ClangBackEnd::ClangQueryGatherer empthyGatherer{&filePathCache, {}, {unsaved.clone()}, query.clone()};
ASSERT_FALSE(empthyGatherer.canCreateSourceRangesAndDiagnostics()); ASSERT_FALSE(empthyGatherer.canCreateSourceRangesAndDiagnostics());
} }

View File

@@ -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(), "");
}
}

View File

@@ -73,7 +73,7 @@ protected:
PathString main2Path = TESTDATA_DIR "/includecollector_main2.cpp"; PathString main2Path = TESTDATA_DIR "/includecollector_main2.cpp";
PathString header1Path = TESTDATA_DIR "/includecollector_header1.h"; PathString header1Path = TESTDATA_DIR "/includecollector_header1.h";
PathString header2Path = TESTDATA_DIR "/includecollector_header2.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"; PathString generatedFilePath = TESTDATA_DIR "/includecollector_generated_file.h";
ProjectPartContainer projectPart1{"project1", ProjectPartContainer projectPart1{"project1",
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"}, {"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},

View File

@@ -28,23 +28,12 @@
#include <sourcerangeextractor.h> #include <sourcerangeextractor.h>
#include <sourcerangescontainer.h> #include <sourcerangescontainer.h>
#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 <clang/Basic/SourceManager.h> #include <clang/Basic/SourceManager.h>
#include <clang/Lex/Lexer.h> #include <clang/Lex/Lexer.h>
#if defined(__GNUC__) #include <mutex>
# pragma GCC diagnostic pop
#elif defined(_MSC_VER)
# pragma warning(pop)
#endif
using testing::Contains; using testing::Contains;
using ::testing::Eq; using ::testing::Eq;
@@ -65,7 +54,8 @@ protected:
TestClangTool clangTool{TESTDATA_DIR, "sourcerangeextractor_location.cpp", "", {"cc", "sourcerangeextractor_location.cpp"}}; TestClangTool clangTool{TESTDATA_DIR, "sourcerangeextractor_location.cpp", "", {"cc", "sourcerangeextractor_location.cpp"}};
ClangBackEnd::SourceRangesContainer sourceRangesContainer; ClangBackEnd::SourceRangesContainer sourceRangesContainer;
const clang::SourceManager &sourceManager{clangTool.sourceManager()}; 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 startLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID());
clang::SourceLocation endLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID()).getLocWithOffset(4); clang::SourceLocation endLocation = sourceManager.getLocForStartOfFile(sourceManager.getMainFileID()).getLocWithOffset(4);
clang::SourceRange sourceRange{startLocation, endLocation}; clang::SourceRange sourceRange{startLocation, endLocation};
@@ -76,7 +66,7 @@ using SourceRangeExtractorSlowTest = SourceRangeExtractor;
TEST_F(SourceRangeExtractorSlowTest, ExtractSourceRangeContainer) 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); extractor.addSourceRange(sourceRange);

View File

@@ -63,6 +63,8 @@ SOURCES += \
projectupdater-test.cpp \ projectupdater-test.cpp \
pchmanagerserver-test.cpp \ pchmanagerserver-test.cpp \
pchmanagerclientserverinprocess-test.cpp \ pchmanagerclientserverinprocess-test.cpp \
clangquerygatherer-test.cpp \
filepath-test.cpp
!isEmpty(LIBCLANG_LIBS) { !isEmpty(LIBCLANG_LIBS) {
SOURCES += \ SOURCES += \