diff options
author | Tim Jenssen <tim.jenssen@qt.io> | 2016-11-15 15:38:12 +0100 |
---|---|---|
committer | Tim Jenssen <tim.jenssen@qt.io> | 2016-11-15 15:30:33 +0000 |
commit | 9c7ff5199f77ad668eb48891c3d917a97ca7249a (patch) | |
tree | 4b9f062291d1932bda9c590bd169061df4da1f30 /src/tools/clangrefactoringbackend/source/refactoringserver.cpp | |
parent | 96187594b52b70951724637bf93ae7ba6cea8733 (diff) | |
download | qt-creator-9c7ff5199f77ad668eb48891c3d917a97ca7249a.tar.gz |
Clang: Add clang query
Clang query is mechanism to use AST matcher to search for code. Think
about regular expression but in the context of AST. So you get a semantic
search tool for C++.
Change-Id: I72e882c5b53a0c52f352a3664847c4c3e4f6fc2e
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
Diffstat (limited to 'src/tools/clangrefactoringbackend/source/refactoringserver.cpp')
-rw-r--r-- | src/tools/clangrefactoringbackend/source/refactoringserver.cpp | 92 |
1 files changed, 87 insertions, 5 deletions
diff --git a/src/tools/clangrefactoringbackend/source/refactoringserver.cpp b/src/tools/clangrefactoringbackend/source/refactoringserver.cpp index d4725808b0..e66dce78c7 100644 --- a/src/tools/clangrefactoringbackend/source/refactoringserver.cpp +++ b/src/tools/clangrefactoringbackend/source/refactoringserver.cpp @@ -26,18 +26,24 @@ #include "refactoringserver.h" #include "symbolfinder.h" +#include "clangquery.h" #include <refactoringclientinterface.h> #include <requestsourcelocationforrenamingmessage.h> +#include <requestsourcerangesanddiagnosticsforquerymessage.h> #include <sourcelocationsforrenamingmessage.h> +#include <sourcerangesanddiagnosticsforquerymessage.h> #include <QCoreApplication> +#include <algorithm> +#include <chrono> +#include <future> + namespace ClangBackEnd { RefactoringServer::RefactoringServer() { - } void RefactoringServer::end() @@ -56,10 +62,86 @@ void RefactoringServer::requestSourceLocationsForRenamingMessage(RequestSourceLo symbolFinder.findSymbol(); - client()->sourceLocationsForRenamingMessage(SourceLocationsForRenamingMessage( - symbolFinder.takeSymbolName(), - symbolFinder.takeSourceLocations(), - message.textDocumentRevision())); + client()->sourceLocationsForRenamingMessage({symbolFinder.takeSymbolName(), + symbolFinder.takeSourceLocations(), + message.textDocumentRevision()}); +} + +namespace { + +SourceRangesAndDiagnosticsForQueryMessage createSourceRangesAndDiagnosticsForQueryMessage( + V2::FileContainer &&fileContainer, + Utils::SmallString &&query) { + ClangQuery clangQuery(std::move(query)); + + clangQuery.addFile(fileContainer.filePath().directory(), + fileContainer.filePath().name(), + fileContainer.takeUnsavedFileContent(), + fileContainer.takeCommandLineArguments()); + + clangQuery.findLocations(); + + return {clangQuery.takeSourceRanges(), clangQuery.takeDiagnosticContainers()}; +} + + +} + +void RefactoringServer::requestSourceRangesAndDiagnosticsForQueryMessage( + RequestSourceRangesAndDiagnosticsForQueryMessage &&message) +{ + gatherSourceRangesAndDiagnosticsForQueryMessage(message.takeFileContainers(), message.takeQuery()); +} + +void RefactoringServer::gatherSourceRangesAndDiagnosticsForQueryMessage( + std::vector<V2::FileContainer> &&fileContainers, + Utils::SmallString &&query) +{ + std::vector<Future> futures; + + std::size_t freeProcessors = std::thread::hardware_concurrency(); + + while (!fileContainers.empty() || !futures.empty()) { + --freeProcessors; + + if (!fileContainers.empty()) { + Future &&future = std::async(std::launch::async, + createSourceRangesAndDiagnosticsForQueryMessage, + std::move(fileContainers.back()), + query.clone()); + fileContainers.pop_back(); + + futures.emplace_back(std::move(future)); + } + + if (freeProcessors == 0 || fileContainers.empty()) + freeProcessors += waitForNewSourceRangesAndDiagnosticsForQueryMessage(futures); + } +} + +std::size_t RefactoringServer::waitForNewSourceRangesAndDiagnosticsForQueryMessage(std::vector<Future> &futures) +{ + while (true) { + std::vector<Future> readyFutures; + readyFutures.reserve(futures.size()); + + auto beginReady = std::partition(futures.begin(), + futures.end(), + [] (const Future &future) { + return future.wait_for(std::chrono::duration<int>::zero()) != std::future_status::ready; + }); + + std::move(beginReady, futures.end(), std::back_inserter(readyFutures)); + futures.erase(beginReady, futures.end()); + + for (Future &readyFuture : readyFutures) + client()->sourceRangesAndDiagnosticsForQueryMessage(std::move(readyFuture.get())); + + if (readyFutures.empty()) + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + else + return readyFutures.size(); + } } } // namespace ClangBackEnd |