From 9c7ff5199f77ad668eb48891c3d917a97ca7249a Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Tue, 15 Nov 2016 15:38:12 +0100 Subject: 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 --- .../source/refactoringserver.cpp | 92 ++++++++++++++++++++-- 1 file changed, 87 insertions(+), 5 deletions(-) (limited to 'src/tools/clangrefactoringbackend/source/refactoringserver.cpp') 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 #include +#include #include +#include #include +#include +#include +#include + 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 &&fileContainers, + Utils::SmallString &&query) +{ + std::vector 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 &futures) +{ + while (true) { + std::vector readyFutures; + readyFutures.reserve(futures.size()); + + auto beginReady = std::partition(futures.begin(), + futures.end(), + [] (const Future &future) { + return future.wait_for(std::chrono::duration::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 -- cgit v1.2.1