diff options
author | Marco Bubke <marco.bubke@qt.io> | 2016-11-30 15:29:36 +0100 |
---|---|---|
committer | Marco Bubke <marco.bubke@qt.io> | 2016-12-07 11:39:11 +0000 |
commit | 15de02ea0c92948e1c51b5da11541c2d382b79ca (patch) | |
tree | d2e9b0c10aea7f06ed0d31a1402f0b93f979dd6b /src/tools/clangrefactoringbackend/source | |
parent | 636eea99f498bdb6542610a160ce4e8fa9be0cfe (diff) | |
download | qt-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')
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); |