|
14 | 14 | #include "ParsedAST.h" |
15 | 15 | #include "Protocol.h" |
16 | 16 | #include "Quality.h" |
| 17 | +#include "Query.h" |
| 18 | +#include "QuerySession.h" |
17 | 19 | #include "Selection.h" |
18 | 20 | #include "SourceCode.h" |
19 | 21 | #include "URI.h" |
|
41 | 43 | #include "clang/AST/StmtCXX.h" |
42 | 44 | #include "clang/AST/StmtVisitor.h" |
43 | 45 | #include "clang/AST/Type.h" |
| 46 | +#include "clang/ASTMatchers/ASTMatchFinder.h" |
| 47 | +#include "clang/ASTMatchers/ASTMatchers.h" |
| 48 | +#include "clang/ASTMatchers/Dynamic/Diagnostics.h" |
| 49 | +#include "clang/ASTMatchers/Dynamic/Parser.h" |
44 | 50 | #include "clang/Basic/LLVM.h" |
45 | 51 | #include "clang/Basic/LangOptions.h" |
46 | 52 | #include "clang/Basic/SourceLocation.h" |
|
52 | 58 | #include "clang/Index/IndexingOptions.h" |
53 | 59 | #include "clang/Index/USRGeneration.h" |
54 | 60 | #include "clang/Lex/Lexer.h" |
| 61 | +#include "clang/Parse/Parser.h" |
55 | 62 | #include "clang/Sema/HeuristicResolver.h" |
56 | 63 | #include "clang/Tooling/Syntax/Tokens.h" |
57 | 64 | #include "llvm/ADT/ArrayRef.h" |
|
66 | 73 | #include "llvm/Support/ErrorHandling.h" |
67 | 74 | #include "llvm/Support/Path.h" |
68 | 75 | #include "llvm/Support/raw_ostream.h" |
| 76 | +#include <cmath> |
69 | 77 | #include <optional> |
70 | 78 | #include <string> |
71 | 79 | #include <vector> |
@@ -773,6 +781,61 @@ const syntax::Token *findNearbyIdentifier(const SpelledWord &Word, |
773 | 781 | return BestTok; |
774 | 782 | } |
775 | 783 |
|
| 784 | +auto locateASTQuery(ParsedAST &AST, SearchASTArgs const &Query) |
| 785 | + -> std::vector<ast_matchers::BoundNodes> { |
| 786 | + using namespace ast_matchers; |
| 787 | + using namespace ast_matchers::dynamic; |
| 788 | + using ast_matchers::dynamic::Parser; |
| 789 | + |
| 790 | + Diagnostics Diag; |
| 791 | + auto MatcherSource = llvm::StringRef(Query.searchQuery).ltrim(); |
| 792 | + auto OrigMatcherSource = MatcherSource; |
| 793 | + |
| 794 | + std::optional<DynTypedMatcher> Matcher = Parser::parseMatcherExpression( |
| 795 | + MatcherSource, |
| 796 | + nullptr /* is this sema instance usefull, to reduce overhead?*/, |
| 797 | + nullptr /*we currently don't support let*/, &Diag); |
| 798 | + if (!Matcher) { |
| 799 | + elog("Not a valid top-level matcher.\n"); |
| 800 | + return {/* TODO */}; |
| 801 | + } |
| 802 | + auto ActualSource = OrigMatcherSource.slice(0, OrigMatcherSource.size() - |
| 803 | + MatcherSource.size()); |
| 804 | + auto *Q = new query::MatchQuery(ActualSource, *Matcher); |
| 805 | + Q->RemainingContent = MatcherSource; |
| 806 | + |
| 807 | + // Q->run(AST);: |
| 808 | + //== |
| 809 | + |
| 810 | + struct CollectBoundNodes : MatchFinder::MatchCallback { |
| 811 | + std::vector<BoundNodes> &Bindings; |
| 812 | + CollectBoundNodes(std::vector<BoundNodes> &Bindings) : Bindings(Bindings) {} |
| 813 | + void run(const MatchFinder::MatchResult &Result) override { |
| 814 | + Bindings.push_back(Result.Nodes); |
| 815 | + } |
| 816 | + }; |
| 817 | + |
| 818 | + MatchFinder Finder; |
| 819 | + std::vector<BoundNodes> Matches; |
| 820 | + DynTypedMatcher MaybeBoundMatcher = *Matcher; |
| 821 | + if (Query.BindRoot) { |
| 822 | + std::optional<DynTypedMatcher> M = Matcher->tryBind("root"); |
| 823 | + if (M) |
| 824 | + MaybeBoundMatcher = *M; |
| 825 | + } |
| 826 | + CollectBoundNodes Collect(Matches); |
| 827 | + if (!Finder.addDynamicMatcher(MaybeBoundMatcher, &Collect)) { |
| 828 | + log("Not a valid top-level matcher.\n"); |
| 829 | + return {/* TODO */}; |
| 830 | + } |
| 831 | + |
| 832 | + ASTContext &Ctx = AST.getASTContext(); |
| 833 | + Ctx.getParentMapContext().setTraversalKind(Query.Tk); |
| 834 | + Finder.matchAST(Ctx); |
| 835 | + |
| 836 | + return Matches; |
| 837 | +} |
| 838 | + |
776 | 839 | std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos, |
777 | 840 | const SymbolIndex *Index) { |
778 | 841 | const auto &SM = AST.getSourceManager(); |
|
0 commit comments