summaryrefslogtreecommitdiff
path: root/src/tools/clangrefactoringbackend/source
diff options
context:
space:
mode:
authorMarco Bubke <marco.bubke@qt.io>2016-11-30 15:29:36 +0100
committerMarco Bubke <marco.bubke@qt.io>2016-12-07 11:39:11 +0000
commit15de02ea0c92948e1c51b5da11541c2d382b79ca (patch)
treed2e9b0c10aea7f06ed0d31a1402f0b93f979dd6b /src/tools/clangrefactoringbackend/source
parent636eea99f498bdb6542610a160ce4e8fa9be0cfe (diff)
downloadqt-creator-15de02ea0c92948e1c51b5da11541c2d382b79ca.tar.gz
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>
Diffstat (limited to 'src/tools/clangrefactoringbackend/source')
-rw-r--r--src/tools/clangrefactoringbackend/source/clangtool.cpp42
-rw-r--r--src/tools/clangrefactoringbackend/source/clangtool.h18
-rw-r--r--src/tools/clangrefactoringbackend/source/refactoringserver.cpp34
-rw-r--r--src/tools/clangrefactoringbackend/source/refactoringserver.h3
4 files changed, 81 insertions, 16 deletions
diff --git a/src/tools/clangrefactoringbackend/source/clangtool.cpp b/src/tools/clangrefactoringbackend/source/clangtool.cpp
index aaef2845e0..1e7520de2d 100644
--- a/src/tools/clangrefactoringbackend/source/clangtool.cpp
+++ b/src/tools/clangrefactoringbackend/source/clangtool.cpp
@@ -31,7 +31,8 @@ namespace {
// 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
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 tool(compilationDatabase, sourceFilePaths);
- for (auto &&fileContent : fileContents) {
+ for (const auto &fileContent : fileContents) {
if (!fileContent.content.empty())
tool.mapVirtualFile(fileContent.filePath, fileContent.content);
}
+ for (const auto &unsavedFileContent : unsavedFileContents)
+ tool.mapVirtualFile(toStringRef(unsavedFileContent.filePath),
+ toStringRef(unsavedFileContent.content));
+
return tool;
}
diff --git a/src/tools/clangrefactoringbackend/source/clangtool.h b/src/tools/clangrefactoringbackend/source/clangtool.h
index b16b7a94dd..fd4ca4b9e5 100644
--- a/src/tools/clangrefactoringbackend/source/clangtool.h
+++ b/src/tools/clangrefactoringbackend/source/clangtool.h
@@ -29,6 +29,7 @@
#include <clangrefactoringbackend_global.h>
+#include <filecontainerv2.h>
#include <sourcelocationscontainer.h>
#if defined(__GNUC__)
@@ -42,6 +43,8 @@
#pragma GCC diagnostic pop
#endif
+#include <utils/smallstring.h>
+
#include <string>
#include <vector>
@@ -67,6 +70,18 @@ struct FileContent
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
{
public:
@@ -77,12 +92,15 @@ public:
void addFiles(const Utils::SmallStringVector &filePaths,
const Utils::SmallStringVector &arguments);
+ void addUnsavedFiles(std::vector<V2::FileContainer> &&unsavedFiles);
+
clang::tooling::ClangTool createTool() const;
private:
RefactoringCompilationDatabase compilationDatabase;
std::vector<FileContent> fileContents;
std::vector<std::string> sourceFilePaths;
+ std::vector<UnsavedFileContent> unsavedFileContents;
};
} // namespace ClangBackEnd
diff --git a/src/tools/clangrefactoringbackend/source/refactoringserver.cpp b/src/tools/clangrefactoringbackend/source/refactoringserver.cpp
index debc827968..f4e5372e9a 100644
--- a/src/tools/clangrefactoringbackend/source/refactoringserver.cpp
+++ b/src/tools/clangrefactoringbackend/source/refactoringserver.cpp
@@ -72,7 +72,9 @@ void RefactoringServer::requestSourceLocationsForRenamingMessage(RequestSourceLo
void RefactoringServer::requestSourceRangesAndDiagnosticsForQueryMessage(
RequestSourceRangesAndDiagnosticsForQueryMessage &&message)
{
- gatherSourceRangesAndDiagnosticsForQueryMessage(message.takeFileContainers(), message.takeQuery());
+ gatherSourceRangesAndDiagnosticsForQueryMessage(message.takeSources(),
+ message.takeUnsavedContent(),
+ message.takeQuery());
}
void RefactoringServer::cancel()
@@ -93,16 +95,19 @@ void RefactoringServer::supersedePollEventLoop(std::function<void ()> &&pollEven
namespace {
SourceRangesAndDiagnosticsForQueryMessage createSourceRangesAndDiagnosticsForQueryMessage(
- V2::FileContainer &&fileContainer,
+ V2::FileContainer &&source,
+ std::vector<V2::FileContainer> &&unsaved,
Utils::SmallString &&query,
const std::atomic_bool &cancelWork) {
ClangQuery clangQuery(std::move(query));
if (!cancelWork) {
- clangQuery.addFile(fileContainer.filePath().directory(),
- fileContainer.filePath().name(),
- fileContainer.takeUnsavedFileContent(),
- fileContainer.takeCommandLineArguments());
+ clangQuery.addFile(source.filePath().directory(),
+ source.filePath().name(),
+ source.takeUnsavedFileContent(),
+ source.takeCommandLineArguments());
+
+ clangQuery.addUnsavedFiles(std::move(unsaved));
clangQuery.findLocations();
}
@@ -114,27 +119,30 @@ SourceRangesAndDiagnosticsForQueryMessage createSourceRangesAndDiagnosticsForQue
}
void RefactoringServer::gatherSourceRangesAndDiagnosticsForQueryMessage(
- std::vector<V2::FileContainer> &&fileContainers,
+ std::vector<V2::FileContainer> &&sources,
+ std::vector<V2::FileContainer> &&unsaved,
Utils::SmallString &&query)
{
std::vector<Future> futures;
std::size_t freeProcessors = std::thread::hardware_concurrency();
- while (!fileContainers.empty() || !futures.empty()) {
+ while (!sources.empty() || !futures.empty()) {
--freeProcessors;
- if (!fileContainers.empty()) {
+ if (!sources.empty()) {
Future &&future = std::async(std::launch::async,
createSourceRangesAndDiagnosticsForQueryMessage,
- std::move(fileContainers.back()),
- query.clone(), std::ref(cancelWork));
- fileContainers.pop_back();
+ std::move(sources.back()),
+ Utils::clone(unsaved),
+ query.clone(),
+ std::ref(cancelWork));
+ sources.pop_back();
futures.emplace_back(std::move(future));
}
- if (freeProcessors == 0 || fileContainers.empty())
+ if (freeProcessors == 0 || sources.empty())
freeProcessors += waitForNewSourceRangesAndDiagnosticsForQueryMessage(futures);
}
}
diff --git a/src/tools/clangrefactoringbackend/source/refactoringserver.h b/src/tools/clangrefactoringbackend/source/refactoringserver.h
index f61509e60d..b7d6adfb15 100644
--- a/src/tools/clangrefactoringbackend/source/refactoringserver.h
+++ b/src/tools/clangrefactoringbackend/source/refactoringserver.h
@@ -54,7 +54,8 @@ public:
void supersedePollEventLoop(std::function<void()> &&pollEventLoop);
private:
- void gatherSourceRangesAndDiagnosticsForQueryMessage(std::vector<V2::FileContainer> &&fileContainers,
+ void gatherSourceRangesAndDiagnosticsForQueryMessage(std::vector<V2::FileContainer> &&sources,
+ std::vector<V2::FileContainer> &&unsaved,
Utils::SmallString &&query);
std::size_t waitForNewSourceRangesAndDiagnosticsForQueryMessage(std::vector<Future> &futures);