110 unsigned MatchCount = 0;
112 std::optional<QueryProfiler> Profiler;
116 for (
auto &AST : QS.
ASTs) {
117 ast_matchers::MatchFinder::MatchFinderOptions FinderOptions;
118 std::optional<llvm::StringMap<llvm::TimeRecord>> Records;
121 FinderOptions.CheckProfiling.emplace(*Records);
124 MatchFinder Finder(FinderOptions);
125 std::vector<BoundNodes> Matches;
126 DynTypedMatcher MaybeBoundMatcher =
Matcher;
128 std::optional<DynTypedMatcher> M =
Matcher.tryBind(
"root");
130 MaybeBoundMatcher = *M;
132 StringRef OrigSrcName = AST->getOriginalSourceFileName();
133 CollectBoundNodes Collect(Matches, OrigSrcName);
134 if (!Finder.addDynamicMatcher(MaybeBoundMatcher, &Collect)) {
135 OS <<
"Not a valid top-level matcher.\n";
139 ASTContext &Ctx = AST->getASTContext();
140 Ctx.getParentMapContext().setTraversalKind(QS.
TK);
141 Finder.matchAST(Ctx);
143 Profiler->Records[OrigSrcName] += (*Records)[OrigSrcName];
146 SmallVector<StringRef, 4> Lines;
147 Source.split(Lines,
"\n");
148 auto FirstLine = Lines[0];
149 Lines.erase(Lines.begin(), Lines.begin() + 1);
150 while (!Lines.empty() && Lines.back().empty()) {
151 Lines.resize(Lines.size() - 1);
153 unsigned MaxLength = FirstLine.size();
154 std::string PrefixText =
"Matcher: ";
155 OS <<
"\n " << PrefixText << FirstLine;
157 for (
auto Line : Lines) {
158 OS <<
"\n" << std::string(PrefixText.size() + 2,
' ') << Line;
159 MaxLength = std::max<int>(MaxLength, Line.rtrim().size());
163 <<
" " << std::string(PrefixText.size() + MaxLength,
'=') <<
"\n\n";
166 for (
auto MI = Matches.begin(), ME = Matches.end(); MI != ME; ++MI) {
167 OS <<
"\nMatch #" << ++MatchCount <<
":\n\n";
169 for (
auto BI = MI->getMap().begin(), BE = MI->getMap().end(); BI != BE;
172 clang::SourceRange R = BI->second.getSourceRange();
174 TextDiagnostic TD(OS, AST->getASTContext().getLangOpts(),
175 AST->getDiagnostics().getDiagnosticOptions());
177 FullSourceLoc(R.getBegin(), AST->getSourceManager()),
178 DiagnosticsEngine::Note,
"\"" + BI->first +
"\" binds here",
179 CharSourceRange::getTokenRange(R), {});
183 OS <<
"Binding for \"" << BI->first <<
"\":\n";
184 BI->second.print(OS, AST->getASTContext().getPrintingPolicy());
188 OS <<
"Binding for \"" << BI->first <<
"\":\n";
189 ASTDumper Dumper(OS, Ctx, AST->getDiagnostics().getShowColors());
190 Dumper.SetTraversalKind(QS.
TK);
191 Dumper.Visit(BI->second);
196 if (MI->getMap().empty())
197 OS <<
"No bindings.\n";
201 OS << MatchCount << (MatchCount == 1 ?
" match.\n" :
" matches.\n");
220 auto Buffer = llvm::MemoryBuffer::getFile(StringRef{File}.trim());
222 if (Prefix.has_value())
223 llvm::errs() << *Prefix <<
": ";
224 llvm::errs() <<
"cannot open " << File <<
": "
225 << Buffer.getError().message() <<
"\n";
229 StringRef FileContentRef(Buffer.get()->getBuffer());
231 while (!FileContentRef.empty()) {
233 if (!Q->run(llvm::outs(), QS))
235 FileContentRef = Q->RemainingContent;