summaryrefslogtreecommitdiff
path: root/src/tools/clangrefactoringbackend/source/refactoringserver.cpp
diff options
context:
space:
mode:
authorTim Jenssen <tim.jenssen@qt.io>2016-11-15 15:38:12 +0100
committerTim Jenssen <tim.jenssen@qt.io>2016-11-15 15:30:33 +0000
commit9c7ff5199f77ad668eb48891c3d917a97ca7249a (patch)
tree4b9f062291d1932bda9c590bd169061df4da1f30 /src/tools/clangrefactoringbackend/source/refactoringserver.cpp
parent96187594b52b70951724637bf93ae7ba6cea8733 (diff)
downloadqt-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.cpp92
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