forked from qt-creator/qt-creator
Clang: Add refactoring support for unsaved content
We need the generated UI header but we don't have a build directory. So we provide clang with in memory represations of the file. Change-Id: Ie9db97bbea2222b0203a0457baa1f1fc7ad97213 Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -31,7 +31,7 @@ QDebug operator<<(QDebug debug, const RequestSourceRangesAndDiagnosticsForQueryM
|
|||||||
{
|
{
|
||||||
debug.nospace() << "RequestSourceRangesAndDiagnosticsForQuery("
|
debug.nospace() << "RequestSourceRangesAndDiagnosticsForQuery("
|
||||||
<< message.query() << ", "
|
<< message.query() << ", "
|
||||||
<< message.fileContainers() << ")";
|
<< message.sources() << ")";
|
||||||
|
|
||||||
return debug;
|
return debug;
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ void PrintTo(const RequestSourceRangesAndDiagnosticsForQueryMessage &message, ::
|
|||||||
#ifdef UNIT_TESTS
|
#ifdef UNIT_TESTS
|
||||||
*os << "RequestSourceRangesAndDiagnosticsForQuery("
|
*os << "RequestSourceRangesAndDiagnosticsForQuery("
|
||||||
<< message.query() << ", "
|
<< message.query() << ", "
|
||||||
<< message.fileContainers()
|
<< message.sources()
|
||||||
<< ")";
|
<< ")";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@@ -34,19 +34,32 @@ class RequestSourceRangesAndDiagnosticsForQueryMessage
|
|||||||
public:
|
public:
|
||||||
RequestSourceRangesAndDiagnosticsForQueryMessage() = default;
|
RequestSourceRangesAndDiagnosticsForQueryMessage() = default;
|
||||||
RequestSourceRangesAndDiagnosticsForQueryMessage(Utils::SmallString &&query,
|
RequestSourceRangesAndDiagnosticsForQueryMessage(Utils::SmallString &&query,
|
||||||
std::vector<V2::FileContainer> &&fileContainers)
|
std::vector<V2::FileContainer> &&sources,
|
||||||
|
std::vector<V2::FileContainer> &&unsavedContent)
|
||||||
: query_(std::move(query)),
|
: query_(std::move(query)),
|
||||||
fileContainers_(std::move(fileContainers))
|
sources_(std::move(sources)),
|
||||||
|
unsavedContent_(std::move(unsavedContent))
|
||||||
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
const std::vector<V2::FileContainer> &fileContainers() const
|
const std::vector<V2::FileContainer> &sources() const
|
||||||
{
|
{
|
||||||
return fileContainers_;
|
return sources_;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<V2::FileContainer> takeFileContainers()
|
std::vector<V2::FileContainer> takeSources()
|
||||||
{
|
{
|
||||||
return std::move(fileContainers_);
|
return std::move(sources_);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<V2::FileContainer> &unsavedContent() const
|
||||||
|
{
|
||||||
|
return unsavedContent_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<V2::FileContainer> takeUnsavedContent()
|
||||||
|
{
|
||||||
|
return std::move(unsavedContent_);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Utils::SmallString &query() const
|
const Utils::SmallString &query() const
|
||||||
@@ -62,7 +75,8 @@ public:
|
|||||||
friend QDataStream &operator<<(QDataStream &out, const RequestSourceRangesAndDiagnosticsForQueryMessage &message)
|
friend QDataStream &operator<<(QDataStream &out, const RequestSourceRangesAndDiagnosticsForQueryMessage &message)
|
||||||
{
|
{
|
||||||
out << message.query_;
|
out << message.query_;
|
||||||
out << message.fileContainers_;
|
out << message.sources_;
|
||||||
|
out << message.unsavedContent_;
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -70,7 +84,8 @@ public:
|
|||||||
friend QDataStream &operator>>(QDataStream &in, RequestSourceRangesAndDiagnosticsForQueryMessage &message)
|
friend QDataStream &operator>>(QDataStream &in, RequestSourceRangesAndDiagnosticsForQueryMessage &message)
|
||||||
{
|
{
|
||||||
in >> message.query_;
|
in >> message.query_;
|
||||||
in >> message.fileContainers_;
|
in >> message.sources_;
|
||||||
|
in >> message.unsavedContent_;
|
||||||
|
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
@@ -79,19 +94,21 @@ public:
|
|||||||
const RequestSourceRangesAndDiagnosticsForQueryMessage &second)
|
const RequestSourceRangesAndDiagnosticsForQueryMessage &second)
|
||||||
{
|
{
|
||||||
return first.query_ == second.query_
|
return first.query_ == second.query_
|
||||||
&& first.fileContainers_ == second.fileContainers_;
|
&& first.sources_ == second.sources_
|
||||||
|
&& first.unsavedContent_ == second.unsavedContent_;
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestSourceRangesAndDiagnosticsForQueryMessage clone() const
|
RequestSourceRangesAndDiagnosticsForQueryMessage clone() const
|
||||||
{
|
{
|
||||||
return RequestSourceRangesAndDiagnosticsForQueryMessage(query_.clone(),
|
return RequestSourceRangesAndDiagnosticsForQueryMessage(query_.clone(),
|
||||||
Utils::clone(fileContainers_));
|
Utils::clone(sources_),
|
||||||
|
Utils::clone(unsavedContent_));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Utils::SmallString query_;
|
Utils::SmallString query_;
|
||||||
std::vector<V2::FileContainer> fileContainers_;
|
std::vector<V2::FileContainer> sources_;
|
||||||
|
std::vector<V2::FileContainer> unsavedContent_;
|
||||||
};
|
};
|
||||||
|
|
||||||
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const RequestSourceRangesAndDiagnosticsForQueryMessage &message);
|
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const RequestSourceRangesAndDiagnosticsForQueryMessage &message);
|
||||||
|
@@ -70,7 +70,7 @@ void ClangQueryProjectsFindFilter::findAll(const QString &queryText, Core::FindF
|
|||||||
|
|
||||||
auto message = createMessage(queryText);
|
auto message = createMessage(queryText);
|
||||||
|
|
||||||
refactoringClient.setExpectedResultCount(message.fileContainers().size());
|
refactoringClient.setExpectedResultCount(message.sources().size());
|
||||||
|
|
||||||
server.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(message));
|
server.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(message));
|
||||||
}
|
}
|
||||||
@@ -100,6 +100,12 @@ SearchHandle *ClangQueryProjectsFindFilter::searchHandleForTestOnly() const
|
|||||||
return searchHandle.get();
|
return searchHandle.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClangQueryProjectsFindFilter::setUnsavedContent(
|
||||||
|
std::vector<ClangBackEnd::V2::FileContainer> &&unsavedContent)
|
||||||
|
{
|
||||||
|
this->unsavedContent = std::move(unsavedContent);
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
Utils::SmallStringVector createCommandLine(CppTools::ProjectPart *projectPart,
|
Utils::SmallStringVector createCommandLine(CppTools::ProjectPart *projectPart,
|
||||||
@@ -118,13 +124,13 @@ Utils::SmallStringVector createCommandLine(CppTools::ProjectPart *projectPart,
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ClangBackEnd::V2::FileContainer>
|
std::vector<ClangBackEnd::V2::FileContainer>
|
||||||
createFileContainers(const std::vector<CppTools::ProjectPart::Ptr> &projectParts)
|
createSources(const std::vector<CppTools::ProjectPart::Ptr> &projectParts)
|
||||||
{
|
{
|
||||||
std::vector<ClangBackEnd::V2::FileContainer> fileContainers;
|
std::vector<ClangBackEnd::V2::FileContainer> sources;
|
||||||
|
|
||||||
for (const CppTools::ProjectPart::Ptr &projectPart : projectParts) {
|
for (const CppTools::ProjectPart::Ptr &projectPart : projectParts) {
|
||||||
for (const CppTools::ProjectFile &projectFile : projectPart->files) {
|
for (const CppTools::ProjectFile &projectFile : projectPart->files) {
|
||||||
fileContainers.emplace_back(ClangBackEnd::FilePath(projectFile.path),
|
sources.emplace_back(ClangBackEnd::FilePath(projectFile.path),
|
||||||
"",
|
"",
|
||||||
createCommandLine(projectPart.data(),
|
createCommandLine(projectPart.data(),
|
||||||
projectFile.path,
|
projectFile.path,
|
||||||
@@ -132,15 +138,17 @@ createFileContainers(const std::vector<CppTools::ProjectPart::Ptr> &projectParts
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fileContainers;
|
return sources;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage ClangQueryProjectsFindFilter::createMessage(const QString &queryText) const
|
ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage ClangQueryProjectsFindFilter::createMessage(const QString &queryText) const
|
||||||
{
|
{
|
||||||
return ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage(
|
return ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage(
|
||||||
Utils::SmallString(queryText),
|
Utils::SmallString(queryText),
|
||||||
createFileContainers(projectParts));
|
createSources(projectParts),
|
||||||
|
Utils::clone(unsavedContent));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -31,6 +31,8 @@
|
|||||||
|
|
||||||
#include <coreplugin/find/ifindfilter.h>
|
#include <coreplugin/find/ifindfilter.h>
|
||||||
|
|
||||||
|
#include <filecontainerv2.h>
|
||||||
|
|
||||||
#include <utils/smallstringvector.h>
|
#include <utils/smallstringvector.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -65,11 +67,14 @@ public:
|
|||||||
|
|
||||||
SearchHandle* searchHandleForTestOnly() const;
|
SearchHandle* searchHandleForTestOnly() const;
|
||||||
|
|
||||||
|
void setUnsavedContent(std::vector<ClangBackEnd::V2::FileContainer> &&unsavedContent);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage createMessage(
|
ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage createMessage(
|
||||||
const QString &queryText) const;
|
const QString &queryText) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::vector<ClangBackEnd::V2::FileContainer> unsavedContent;
|
||||||
std::unique_ptr<SearchHandle> searchHandle;
|
std::unique_ptr<SearchHandle> searchHandle;
|
||||||
std::vector<CppTools::ProjectPart::Ptr> projectParts;
|
std::vector<CppTools::ProjectPart::Ptr> projectParts;
|
||||||
ClangBackEnd::RefactoringServerInterface &server;
|
ClangBackEnd::RefactoringServerInterface &server;
|
||||||
|
@@ -25,11 +25,14 @@
|
|||||||
|
|
||||||
#include "qtcreatorclangqueryfindfilter.h"
|
#include "qtcreatorclangqueryfindfilter.h"
|
||||||
|
|
||||||
|
#include <cpptools/abstracteditorsupport.h>
|
||||||
#include <cpptools/cppmodelmanager.h>
|
#include <cpptools/cppmodelmanager.h>
|
||||||
#include <cpptools/projectinfo.h>
|
#include <cpptools/projectinfo.h>
|
||||||
|
|
||||||
#include <projectexplorer/session.h>
|
#include <projectexplorer/session.h>
|
||||||
|
|
||||||
|
#include <utils/smallstring.h>
|
||||||
|
|
||||||
namespace ClangRefactoring {
|
namespace ClangRefactoring {
|
||||||
|
|
||||||
QtCreatorClangQueryFindFilter::QtCreatorClangQueryFindFilter(ClangBackEnd::RefactoringServerInterface &server,
|
QtCreatorClangQueryFindFilter::QtCreatorClangQueryFindFilter(ClangBackEnd::RefactoringServerInterface &server,
|
||||||
@@ -58,6 +61,26 @@ convertProjectParts(const QList<CppTools::ProjectPart::Ptr> &projectPartList)
|
|||||||
return projectPartVector;
|
return projectPartVector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<ClangBackEnd::V2::FileContainer> createUnsavedContents()
|
||||||
|
{
|
||||||
|
auto abstractEditors = CppTools::CppModelManager::instance()->abstractEditorSupports();
|
||||||
|
std::vector<ClangBackEnd::V2::FileContainer> unsavedContents;
|
||||||
|
unsavedContents.reserve(abstractEditors.size());
|
||||||
|
|
||||||
|
auto toFileContainer = [] (const CppTools::AbstractEditorSupport *abstractEditor) {
|
||||||
|
return ClangBackEnd::V2::FileContainer(ClangBackEnd::FilePath(abstractEditor->fileName()),
|
||||||
|
Utils::SmallString::fromQByteArray(abstractEditor->contents()),
|
||||||
|
{});
|
||||||
|
};
|
||||||
|
|
||||||
|
std::transform(abstractEditors.begin(),
|
||||||
|
abstractEditors.end(),
|
||||||
|
std::back_inserter(unsavedContents),
|
||||||
|
toFileContainer);
|
||||||
|
|
||||||
|
return unsavedContents;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtCreatorClangQueryFindFilter::prepareFind()
|
void QtCreatorClangQueryFindFilter::prepareFind()
|
||||||
@@ -67,6 +90,8 @@ void QtCreatorClangQueryFindFilter::prepareFind()
|
|||||||
const CppTools::ProjectInfo projectInfo = CppTools::CppModelManager::instance()->projectInfo(currentProject);
|
const CppTools::ProjectInfo projectInfo = CppTools::CppModelManager::instance()->projectInfo(currentProject);
|
||||||
|
|
||||||
setProjectParts(convertProjectParts(projectInfo.projectParts()));
|
setProjectParts(convertProjectParts(projectInfo.projectParts()));
|
||||||
|
|
||||||
|
setUnsavedContent(createUnsavedContents());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ClangRefactoring
|
} // namespace ClangRefactoring
|
||||||
|
@@ -31,7 +31,8 @@ namespace {
|
|||||||
|
|
||||||
// use std::filesystem::path if it is supported by all compilers
|
// use std::filesystem::path if it is supported by all compilers
|
||||||
|
|
||||||
std::string toNativePath(std::string &&path)
|
template <typename String>
|
||||||
|
String toNativePath(String &&path)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
std::replace(path.begin(), path.end(), '/', '\\');
|
std::replace(path.begin(), path.end(), '/', '\\');
|
||||||
@@ -75,15 +76,52 @@ void ClangTool::addFiles(const Utils::SmallStringVector &filePaths,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(std::vector<V2::FileContainer> &&unsavedFiles)
|
||||||
|
{
|
||||||
|
unsavedFileContents.reserve(unsavedFileContents.size() + unsavedFiles.size());
|
||||||
|
|
||||||
|
auto convertToUnsavedFileContent = [] (V2::FileContainer &unsavedFile) {
|
||||||
|
return UnsavedFileContent{toNativeFilePath(unsavedFile.filePath()),
|
||||||
|
unsavedFile.takeUnsavedFileContent()};
|
||||||
|
};
|
||||||
|
|
||||||
|
std::transform(unsavedFiles.begin(),
|
||||||
|
unsavedFiles.end(),
|
||||||
|
std::back_inserter(unsavedFileContents),
|
||||||
|
convertToUnsavedFileContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
llvm::StringRef toStringRef(const Utils::SmallString &string)
|
||||||
|
{
|
||||||
|
return llvm::StringRef(string.data(), string.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
clang::tooling::ClangTool ClangTool::createTool() const
|
clang::tooling::ClangTool ClangTool::createTool() const
|
||||||
{
|
{
|
||||||
clang::tooling::ClangTool tool(compilationDatabase, sourceFilePaths);
|
clang::tooling::ClangTool tool(compilationDatabase, sourceFilePaths);
|
||||||
|
|
||||||
for (auto &&fileContent : fileContents) {
|
for (const auto &fileContent : fileContents) {
|
||||||
if (!fileContent.content.empty())
|
if (!fileContent.content.empty())
|
||||||
tool.mapVirtualFile(fileContent.filePath, fileContent.content);
|
tool.mapVirtualFile(fileContent.filePath, fileContent.content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const auto &unsavedFileContent : unsavedFileContents)
|
||||||
|
tool.mapVirtualFile(toStringRef(unsavedFileContent.filePath),
|
||||||
|
toStringRef(unsavedFileContent.content));
|
||||||
|
|
||||||
return tool;
|
return tool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include <clangrefactoringbackend_global.h>
|
#include <clangrefactoringbackend_global.h>
|
||||||
|
|
||||||
|
#include <filecontainerv2.h>
|
||||||
#include <sourcelocationscontainer.h>
|
#include <sourcelocationscontainer.h>
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
@@ -42,6 +43,8 @@
|
|||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <utils/smallstring.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -67,6 +70,18 @@ struct FileContent
|
|||||||
std::vector<std::string> commandLine;
|
std::vector<std::string> commandLine;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct UnsavedFileContent
|
||||||
|
{
|
||||||
|
UnsavedFileContent(Utils::SmallString &&filePath,
|
||||||
|
Utils::SmallString &&content)
|
||||||
|
: filePath(std::move(filePath)),
|
||||||
|
content(std::move(content))
|
||||||
|
{}
|
||||||
|
|
||||||
|
Utils::SmallString filePath;
|
||||||
|
Utils::SmallString content;
|
||||||
|
};
|
||||||
|
|
||||||
class ClangTool
|
class ClangTool
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -77,12 +92,15 @@ public:
|
|||||||
void addFiles(const Utils::SmallStringVector &filePaths,
|
void addFiles(const Utils::SmallStringVector &filePaths,
|
||||||
const Utils::SmallStringVector &arguments);
|
const Utils::SmallStringVector &arguments);
|
||||||
|
|
||||||
|
void addUnsavedFiles(std::vector<V2::FileContainer> &&unsavedFiles);
|
||||||
|
|
||||||
clang::tooling::ClangTool createTool() const;
|
clang::tooling::ClangTool createTool() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RefactoringCompilationDatabase compilationDatabase;
|
RefactoringCompilationDatabase compilationDatabase;
|
||||||
std::vector<FileContent> fileContents;
|
std::vector<FileContent> fileContents;
|
||||||
std::vector<std::string> sourceFilePaths;
|
std::vector<std::string> sourceFilePaths;
|
||||||
|
std::vector<UnsavedFileContent> unsavedFileContents;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ClangBackEnd
|
} // namespace ClangBackEnd
|
||||||
|
@@ -72,7 +72,9 @@ void RefactoringServer::requestSourceLocationsForRenamingMessage(RequestSourceLo
|
|||||||
void RefactoringServer::requestSourceRangesAndDiagnosticsForQueryMessage(
|
void RefactoringServer::requestSourceRangesAndDiagnosticsForQueryMessage(
|
||||||
RequestSourceRangesAndDiagnosticsForQueryMessage &&message)
|
RequestSourceRangesAndDiagnosticsForQueryMessage &&message)
|
||||||
{
|
{
|
||||||
gatherSourceRangesAndDiagnosticsForQueryMessage(message.takeFileContainers(), message.takeQuery());
|
gatherSourceRangesAndDiagnosticsForQueryMessage(message.takeSources(),
|
||||||
|
message.takeUnsavedContent(),
|
||||||
|
message.takeQuery());
|
||||||
}
|
}
|
||||||
|
|
||||||
void RefactoringServer::cancel()
|
void RefactoringServer::cancel()
|
||||||
@@ -93,16 +95,19 @@ void RefactoringServer::supersedePollEventLoop(std::function<void ()> &&pollEven
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
SourceRangesAndDiagnosticsForQueryMessage createSourceRangesAndDiagnosticsForQueryMessage(
|
SourceRangesAndDiagnosticsForQueryMessage createSourceRangesAndDiagnosticsForQueryMessage(
|
||||||
V2::FileContainer &&fileContainer,
|
V2::FileContainer &&source,
|
||||||
|
std::vector<V2::FileContainer> &&unsaved,
|
||||||
Utils::SmallString &&query,
|
Utils::SmallString &&query,
|
||||||
const std::atomic_bool &cancelWork) {
|
const std::atomic_bool &cancelWork) {
|
||||||
ClangQuery clangQuery(std::move(query));
|
ClangQuery clangQuery(std::move(query));
|
||||||
|
|
||||||
if (!cancelWork) {
|
if (!cancelWork) {
|
||||||
clangQuery.addFile(fileContainer.filePath().directory(),
|
clangQuery.addFile(source.filePath().directory(),
|
||||||
fileContainer.filePath().name(),
|
source.filePath().name(),
|
||||||
fileContainer.takeUnsavedFileContent(),
|
source.takeUnsavedFileContent(),
|
||||||
fileContainer.takeCommandLineArguments());
|
source.takeCommandLineArguments());
|
||||||
|
|
||||||
|
clangQuery.addUnsavedFiles(std::move(unsaved));
|
||||||
|
|
||||||
clangQuery.findLocations();
|
clangQuery.findLocations();
|
||||||
}
|
}
|
||||||
@@ -114,27 +119,30 @@ SourceRangesAndDiagnosticsForQueryMessage createSourceRangesAndDiagnosticsForQue
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RefactoringServer::gatherSourceRangesAndDiagnosticsForQueryMessage(
|
void RefactoringServer::gatherSourceRangesAndDiagnosticsForQueryMessage(
|
||||||
std::vector<V2::FileContainer> &&fileContainers,
|
std::vector<V2::FileContainer> &&sources,
|
||||||
|
std::vector<V2::FileContainer> &&unsaved,
|
||||||
Utils::SmallString &&query)
|
Utils::SmallString &&query)
|
||||||
{
|
{
|
||||||
std::vector<Future> futures;
|
std::vector<Future> futures;
|
||||||
|
|
||||||
std::size_t freeProcessors = std::thread::hardware_concurrency();
|
std::size_t freeProcessors = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
while (!fileContainers.empty() || !futures.empty()) {
|
while (!sources.empty() || !futures.empty()) {
|
||||||
--freeProcessors;
|
--freeProcessors;
|
||||||
|
|
||||||
if (!fileContainers.empty()) {
|
if (!sources.empty()) {
|
||||||
Future &&future = std::async(std::launch::async,
|
Future &&future = std::async(std::launch::async,
|
||||||
createSourceRangesAndDiagnosticsForQueryMessage,
|
createSourceRangesAndDiagnosticsForQueryMessage,
|
||||||
std::move(fileContainers.back()),
|
std::move(sources.back()),
|
||||||
query.clone(), std::ref(cancelWork));
|
Utils::clone(unsaved),
|
||||||
fileContainers.pop_back();
|
query.clone(),
|
||||||
|
std::ref(cancelWork));
|
||||||
|
sources.pop_back();
|
||||||
|
|
||||||
futures.emplace_back(std::move(future));
|
futures.emplace_back(std::move(future));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (freeProcessors == 0 || fileContainers.empty())
|
if (freeProcessors == 0 || sources.empty())
|
||||||
freeProcessors += waitForNewSourceRangesAndDiagnosticsForQueryMessage(futures);
|
freeProcessors += waitForNewSourceRangesAndDiagnosticsForQueryMessage(futures);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -54,7 +54,8 @@ public:
|
|||||||
void supersedePollEventLoop(std::function<void()> &&pollEventLoop);
|
void supersedePollEventLoop(std::function<void()> &&pollEventLoop);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void gatherSourceRangesAndDiagnosticsForQueryMessage(std::vector<V2::FileContainer> &&fileContainers,
|
void gatherSourceRangesAndDiagnosticsForQueryMessage(std::vector<V2::FileContainer> &&sources,
|
||||||
|
std::vector<V2::FileContainer> &&unsaved,
|
||||||
Utils::SmallString &&query);
|
Utils::SmallString &&query);
|
||||||
std::size_t waitForNewSourceRangesAndDiagnosticsForQueryMessage(std::vector<Future> &futures);
|
std::size_t waitForNewSourceRangesAndDiagnosticsForQueryMessage(std::vector<Future> &futures);
|
||||||
|
|
||||||
|
@@ -74,6 +74,20 @@ TEST_F(ClangQuery, RootSourceRangeForSimpleFunctionDeclarationRange)
|
|||||||
IsSourceRangeWithText(1, 1, 8, 2, "int function(int* pointer, int value)\n{\n if (pointer == nullptr) {\n return value + 1;\n } else {\n return value - 1;\n }\n}"));
|
IsSourceRangeWithText(1, 1, 8, 2, "int function(int* pointer, int value)\n{\n if (pointer == nullptr) {\n return value + 1;\n } else {\n return value - 1;\n }\n}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ClangQuery, SourceRangeInUnsavedFileDeclarationRange)
|
||||||
|
{
|
||||||
|
::ClangQuery query;
|
||||||
|
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();", {}};
|
||||||
|
query.addUnsavedFiles({unsavedFile});
|
||||||
|
|
||||||
|
query.findLocations();
|
||||||
|
|
||||||
|
ASSERT_THAT(query.takeSourceRanges().sourceRangeWithTextContainers().at(0),
|
||||||
|
IsSourceRangeWithText(1, 1, 1, 15, "void unsaved();"));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ClangQuery, RootSourceRangeForSimpleFieldDeclarationRange)
|
TEST_F(ClangQuery, RootSourceRangeForSimpleFieldDeclarationRange)
|
||||||
{
|
{
|
||||||
simpleClassQuery.setQuery("fieldDecl(hasType(isInteger()))");
|
simpleClassQuery.setQuery("fieldDecl(hasType(isInteger()))");
|
||||||
|
@@ -66,6 +66,9 @@ protected:
|
|||||||
QString unsavedDocumentContent{"void f();"};
|
QString unsavedDocumentContent{"void f();"};
|
||||||
std::vector<Utils::SmallStringVector> commandLines;
|
std::vector<Utils::SmallStringVector> commandLines;
|
||||||
std::vector<CppTools::ProjectPart::Ptr> projectsParts;
|
std::vector<CppTools::ProjectPart::Ptr> projectsParts;
|
||||||
|
ClangBackEnd::V2::FileContainer unsavedContent{{"/path/to", "unsaved.cpp"},
|
||||||
|
"void f();",
|
||||||
|
{}};
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(ClangQueryProjectFindFilter, SupportedFindFlags)
|
TEST_F(ClangQueryProjectFindFilter, SupportedFindFlags)
|
||||||
@@ -136,7 +139,8 @@ TEST_F(ClangQueryProjectFindFilter, FindAllIsCallingRequestSourceRangesAndDiagno
|
|||||||
commandLines[1].clone()},
|
commandLines[1].clone()},
|
||||||
{{"/path/to", "file2.cpp"},
|
{{"/path/to", "file2.cpp"},
|
||||||
"",
|
"",
|
||||||
commandLines[2].clone()}});
|
commandLines[2].clone()}},
|
||||||
|
{unsavedContent.clone()});
|
||||||
|
|
||||||
EXPECT_CALL(mockRefactoringServer, requestSourceRangesAndDiagnosticsForQueryMessage(message))
|
EXPECT_CALL(mockRefactoringServer, requestSourceRangesAndDiagnosticsForQueryMessage(message))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
@@ -190,6 +194,8 @@ void ClangQueryProjectFindFilter::SetUp()
|
|||||||
commandLines = createCommandLines(projectsParts);
|
commandLines = createCommandLines(projectsParts);
|
||||||
|
|
||||||
findFilter.setProjectParts(projectsParts);
|
findFilter.setProjectParts(projectsParts);
|
||||||
|
findFilter.setUnsavedContent({unsavedContent.clone()});
|
||||||
|
|
||||||
|
|
||||||
ON_CALL(mockSearch, startNewSearch(QStringLiteral("Clang Query"), findDeclQueryText))
|
ON_CALL(mockSearch, startNewSearch(QStringLiteral("Clang Query"), findDeclQueryText))
|
||||||
.WillByDefault(Return(ByMove(createSearchHandle())));
|
.WillByDefault(Return(ByMove(createSearchHandle())));
|
||||||
|
@@ -135,8 +135,12 @@ TEST_F(RefactoringClientServerInProcess, RequestSourceRangesAndDiagnosticsForQue
|
|||||||
{
|
{
|
||||||
RequestSourceRangesAndDiagnosticsForQueryMessage message{"functionDecl()",
|
RequestSourceRangesAndDiagnosticsForQueryMessage message{"functionDecl()",
|
||||||
{{{TESTDATA_DIR, "query_simplefunction.cpp"},
|
{{{TESTDATA_DIR, "query_simplefunction.cpp"},
|
||||||
"void f();",
|
"void f();",
|
||||||
{"cc", "query_simplefunction.cpp"},
|
{"cc", "query_simplefunction.cpp"},
|
||||||
|
1}},
|
||||||
|
{{{TESTDATA_DIR, "query_simplefunction.h"},
|
||||||
|
"void f();",
|
||||||
|
{},
|
||||||
1}}};
|
1}}};
|
||||||
|
|
||||||
EXPECT_CALL(mockRefactoringServer, requestSourceRangesAndDiagnosticsForQueryMessage(message))
|
EXPECT_CALL(mockRefactoringServer, requestSourceRangesAndDiagnosticsForQueryMessage(message))
|
||||||
|
@@ -72,11 +72,10 @@ class RefactoringServer : public ::testing::Test
|
|||||||
protected:
|
protected:
|
||||||
ClangBackEnd::RefactoringServer refactoringServer;
|
ClangBackEnd::RefactoringServer refactoringServer;
|
||||||
NiceMock<MockRefactoringClient> mockRefactoringClient;
|
NiceMock<MockRefactoringClient> mockRefactoringClient;
|
||||||
Utils::SmallString fileContent{"void f()\n {}"};
|
Utils::SmallString sourceContent{"void f()\n {}"};
|
||||||
FileContainer fileContainer{{TESTDATA_DIR, "query_simplefunction.cpp"},
|
FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"},
|
||||||
fileContent.clone(),
|
sourceContent.clone(),
|
||||||
{"cc", "query_simplefunction.cpp"}};
|
{"cc", "query_simplefunction.cpp"}};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(RefactoringServer, RequestSourceLocationsForRenamingMessage)
|
TEST_F(RefactoringServer, RequestSourceLocationsForRenamingMessage)
|
||||||
@@ -106,13 +105,37 @@ TEST_F(RefactoringServer, RequestSourceLocationsForRenamingMessage)
|
|||||||
TEST_F(RefactoringServer, RequestSingleSourceRangesAndDiagnosticsForQueryMessage)
|
TEST_F(RefactoringServer, RequestSingleSourceRangesAndDiagnosticsForQueryMessage)
|
||||||
{
|
{
|
||||||
RequestSourceRangesAndDiagnosticsForQueryMessage requestSourceRangesAndDiagnosticsForQueryMessage{"functionDecl()",
|
RequestSourceRangesAndDiagnosticsForQueryMessage requestSourceRangesAndDiagnosticsForQueryMessage{"functionDecl()",
|
||||||
{fileContainer.clone()}};
|
{source.clone()},
|
||||||
|
{}};
|
||||||
|
|
||||||
EXPECT_CALL(mockRefactoringClient,
|
EXPECT_CALL(mockRefactoringClient,
|
||||||
sourceRangesAndDiagnosticsForQueryMessage(
|
sourceRangesAndDiagnosticsForQueryMessage(
|
||||||
Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges,
|
Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges,
|
||||||
Property(&SourceRangesContainer::sourceRangeWithTextContainers,
|
Property(&SourceRangesContainer::sourceRangeWithTextContainers,
|
||||||
Contains(IsSourceRangeWithText(1, 1, 2, 4, fileContent))))))
|
Contains(IsSourceRangeWithText(1, 1, 2, 4, sourceContent))))))
|
||||||
|
.Times(1);
|
||||||
|
|
||||||
|
refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(requestSourceRangesAndDiagnosticsForQueryMessage));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RefactoringServer, RequestSingleSourceRangesAndDiagnosticsWithUnsavedContentForQueryMessage)
|
||||||
|
{
|
||||||
|
Utils::SmallString unsavedContent{"void f();"};
|
||||||
|
FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"},
|
||||||
|
"#include \"query_simplefunction.h\"",
|
||||||
|
{"cc", "query_simplefunction.cpp"}};
|
||||||
|
FileContainer unsaved{{TESTDATA_DIR, "query_simplefunction.h"},
|
||||||
|
unsavedContent.clone(),
|
||||||
|
{}};
|
||||||
|
RequestSourceRangesAndDiagnosticsForQueryMessage requestSourceRangesAndDiagnosticsForQueryMessage{"functionDecl()",
|
||||||
|
{source.clone()},
|
||||||
|
{unsaved.clone()}};
|
||||||
|
|
||||||
|
EXPECT_CALL(mockRefactoringClient,
|
||||||
|
sourceRangesAndDiagnosticsForQueryMessage(
|
||||||
|
Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges,
|
||||||
|
Property(&SourceRangesContainer::sourceRangeWithTextContainers,
|
||||||
|
Contains(IsSourceRangeWithText(1, 1, 1, 9, unsavedContent))))))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
|
|
||||||
refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(requestSourceRangesAndDiagnosticsForQueryMessage));
|
refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(requestSourceRangesAndDiagnosticsForQueryMessage));
|
||||||
@@ -121,13 +144,14 @@ TEST_F(RefactoringServer, RequestSingleSourceRangesAndDiagnosticsForQueryMessage
|
|||||||
TEST_F(RefactoringServer, RequestTwoSourceRangesAndDiagnosticsForQueryMessage)
|
TEST_F(RefactoringServer, RequestTwoSourceRangesAndDiagnosticsForQueryMessage)
|
||||||
{
|
{
|
||||||
RequestSourceRangesAndDiagnosticsForQueryMessage requestSourceRangesAndDiagnosticsForQueryMessage{"functionDecl()",
|
RequestSourceRangesAndDiagnosticsForQueryMessage requestSourceRangesAndDiagnosticsForQueryMessage{"functionDecl()",
|
||||||
{fileContainer.clone(), fileContainer.clone()}};
|
{source.clone(), source.clone()},
|
||||||
|
{}};
|
||||||
|
|
||||||
EXPECT_CALL(mockRefactoringClient,
|
EXPECT_CALL(mockRefactoringClient,
|
||||||
sourceRangesAndDiagnosticsForQueryMessage(
|
sourceRangesAndDiagnosticsForQueryMessage(
|
||||||
Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges,
|
Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges,
|
||||||
Property(&SourceRangesContainer::sourceRangeWithTextContainers,
|
Property(&SourceRangesContainer::sourceRangeWithTextContainers,
|
||||||
Contains(IsSourceRangeWithText(1, 1, 2, 4, fileContent))))))
|
Contains(IsSourceRangeWithText(1, 1, 2, 4, sourceContent))))))
|
||||||
.Times(2);
|
.Times(2);
|
||||||
|
|
||||||
refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(requestSourceRangesAndDiagnosticsForQueryMessage));
|
refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(requestSourceRangesAndDiagnosticsForQueryMessage));
|
||||||
@@ -135,18 +159,19 @@ TEST_F(RefactoringServer, RequestTwoSourceRangesAndDiagnosticsForQueryMessage)
|
|||||||
|
|
||||||
TEST_F(RefactoringServer, RequestManySourceRangesAndDiagnosticsForQueryMessage)
|
TEST_F(RefactoringServer, RequestManySourceRangesAndDiagnosticsForQueryMessage)
|
||||||
{
|
{
|
||||||
std::vector<FileContainer> fileContainers;
|
std::vector<FileContainer> sources;
|
||||||
std::fill_n(std::back_inserter(fileContainers),
|
std::fill_n(std::back_inserter(sources),
|
||||||
std::thread::hardware_concurrency() + 3,
|
std::thread::hardware_concurrency() + 3,
|
||||||
fileContainer.clone());
|
source.clone());
|
||||||
RequestSourceRangesAndDiagnosticsForQueryMessage requestSourceRangesAndDiagnosticsForQueryMessage{"functionDecl()",
|
RequestSourceRangesAndDiagnosticsForQueryMessage requestSourceRangesAndDiagnosticsForQueryMessage{"functionDecl()",
|
||||||
std::move(fileContainers)};
|
std::move(sources),
|
||||||
|
{}};
|
||||||
|
|
||||||
EXPECT_CALL(mockRefactoringClient,
|
EXPECT_CALL(mockRefactoringClient,
|
||||||
sourceRangesAndDiagnosticsForQueryMessage(
|
sourceRangesAndDiagnosticsForQueryMessage(
|
||||||
Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges,
|
Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges,
|
||||||
Property(&SourceRangesContainer::sourceRangeWithTextContainers,
|
Property(&SourceRangesContainer::sourceRangeWithTextContainers,
|
||||||
Contains(IsSourceRangeWithText(1, 1, 2, 4, fileContent))))))
|
Contains(IsSourceRangeWithText(1, 1, 2, 4, sourceContent))))))
|
||||||
.Times(std::thread::hardware_concurrency() + 3);
|
.Times(std::thread::hardware_concurrency() + 3);
|
||||||
|
|
||||||
refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(requestSourceRangesAndDiagnosticsForQueryMessage));
|
refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(requestSourceRangesAndDiagnosticsForQueryMessage));
|
||||||
@@ -161,11 +186,13 @@ TEST_F(RefactoringServer, CancelJobs)
|
|||||||
|
|
||||||
TEST_F(RefactoringServer, PollEventLoopAsQueryIsRunning)
|
TEST_F(RefactoringServer, PollEventLoopAsQueryIsRunning)
|
||||||
{
|
{
|
||||||
std::vector<FileContainer> fileContainers;
|
std::vector<FileContainer> sources;
|
||||||
std::fill_n(std::back_inserter(fileContainers),
|
std::fill_n(std::back_inserter(sources),
|
||||||
std::thread::hardware_concurrency() + 3,
|
std::thread::hardware_concurrency() + 3,
|
||||||
fileContainer.clone());
|
source.clone());
|
||||||
RequestSourceRangesAndDiagnosticsForQueryMessage requestSourceRangesAndDiagnosticsForQueryMessage{"functionDecl()", std::move(fileContainers)};
|
RequestSourceRangesAndDiagnosticsForQueryMessage requestSourceRangesAndDiagnosticsForQueryMessage{"functionDecl()",
|
||||||
|
std::move(sources),
|
||||||
|
{}};
|
||||||
bool eventLoopIsPolled = false;
|
bool eventLoopIsPolled = false;
|
||||||
refactoringServer.supersedePollEventLoop([&] () { eventLoopIsPolled = true; });
|
refactoringServer.supersedePollEventLoop([&] () { eventLoopIsPolled = true; });
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user