Last active
May 11, 2020 17:37
-
-
Save FederAndInk/d7e0867b15fa09758e1abfb95a9e20d4 to your computer and use it in GitHub Desktop.
Printing test with clang index (IndexASTConsumer)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <clang/AST/RecursiveASTVisitor.h> | |
#include <clang/Frontend/CompilerInstance.h> | |
#include <clang/Frontend/FrontendActions.h> | |
#include <clang/Index/IndexDataConsumer.h> | |
#include <clang/Index/IndexingAction.h> | |
#include <clang/Tooling/CommonOptionsParser.h> | |
#include <clang/Tooling/Tooling.h> | |
#include <llvm/ADT/DenseMap.h> | |
#include <llvm/ADT/DenseMapInfo.h> | |
#include <llvm/Support/CommandLine.h> | |
#include <string_view> | |
using namespace clang; | |
using namespace clang::tooling; | |
using namespace clang::index; | |
using namespace llvm; | |
std::string generatePointingArrowAt(unsigned int c) | |
{ | |
return std::string(c - 1, ' ') + '^'; | |
} | |
PrintingPolicy default_policy(ASTContext const* ctx) | |
{ | |
PrintingPolicy pp(ctx->getLangOpts()); | |
pp.AnonymousTagLocations = false; | |
pp.TerseOutput = true; | |
pp.PolishForDeclaration = true; | |
pp.ConstantsAsWritten = true; | |
pp.SuppressTagKeyword = false; | |
pp.SuppressUnwrittenScope = false; | |
pp.SuppressInitializers = false; | |
pp.FullyQualifiedName = false; | |
return pp; | |
} | |
class IndexDC : public clang::index::IndexDataConsumer | |
{ | |
ASTContext* ctx = nullptr; | |
public: | |
void initialize(ASTContext& ctx) override | |
{ | |
this->ctx = &ctx; | |
} | |
bool handleDeclOccurrence(const Decl* d, SymbolRoleSet roles, | |
ArrayRef<SymbolRelation> relations, SourceLocation loc, | |
ASTNodeInfo ast_node) override | |
{ | |
SourceManager& sm = ctx->getSourceManager(); | |
auto buf = sm.getBufferData(sm.getFileID(loc)); | |
auto l = sm.getPresumedLineNumber(loc); | |
auto c = sm.getPresumedColumnNumber(loc); | |
outs() << "Presumed: " << l << ":" << c << "\n"; | |
l = sm.getExpansionLineNumber(loc); | |
c = sm.getExpansionColumnNumber(loc); | |
outs() << "Expansion: " << l << ":" << c << "\n"; | |
l = sm.getSpellingLineNumber(loc); | |
c = sm.getSpellingColumnNumber(loc); | |
outs() << "Spelling: " << l << ":" << c << "\n"; | |
outs() << "Roles: "; | |
printSymbolRoles(roles, outs()); | |
outs() << "\n"; | |
outs() << "Kind: " << d->getDeclKindName() << "\n"; | |
if (ast_node.OrigE) | |
{ | |
outs() << "expr: " << ast_node.OrigE->getStmtClassName() << "\n"; | |
} | |
if (auto* nd = dyn_cast<NamedDecl>(d)) | |
{ | |
outs() << "name: " << nd->getDeclName().getAsString() << "\n"; | |
} | |
SmallVector<StringRef, 1> lines; | |
buf.split(lines, "\n"); | |
outs() << l << "|" << lines[l - 1].str() << "\n"; | |
outs() << generatePointingArrowAt(c + 1 + std::to_string(l).size()) << "\n\n"; | |
return true; | |
} | |
}; | |
class ASTDeclNodeLister : public ASTConsumer, | |
public RecursiveASTVisitor<ASTDeclNodeLister> | |
{ | |
public: | |
ASTDeclNodeLister(raw_ostream* Out = nullptr) : Out(Out ? *Out : llvm::outs()) {} | |
void HandleTranslationUnit(ASTContext& Context) override | |
{ | |
TraverseDecl(Context.getTranslationUnitDecl()); | |
} | |
bool shouldWalkTypesOfTypeLocs() const | |
{ | |
return false; | |
} | |
bool VisitNamedDecl(NamedDecl* D) | |
{ | |
D->printQualifiedName(Out); | |
Out << '\n'; | |
return true; | |
} | |
bool VisitCXXConstructExpr(CXXConstructExpr const* expr) | |
{ | |
if (auto* nd = dyn_cast<NamedDecl>(expr->getConstructor())) | |
{ | |
outs() << "name: " << nd->getDeclName().getAsString() << "\n"; | |
} | |
return true; | |
} | |
private: | |
raw_ostream& Out; | |
}; | |
class Action : public clang::ASTFrontendAction | |
{ | |
IndexingOptions opts{.SystemSymbolFilter = IndexingOptions::SystemSymbolFilterKind::All, | |
.IndexFunctionLocals = true, | |
.IndexImplicitInstantiation = true, | |
.IndexParametersInDeclarations = true, | |
.IndexTemplateParameters = true}; | |
public: | |
std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance& ci, | |
StringRef inFile) override | |
{ | |
return createIndexingASTConsumer(std::make_shared<IndexDC>(), opts, | |
ci.getPreprocessorPtr()); | |
} | |
}; | |
class Action2 : public clang::ASTFrontendAction | |
{ | |
public: | |
std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance& ci, | |
StringRef inFile) override | |
{ | |
return std::make_unique<ASTDeclNodeLister>(); | |
} | |
}; | |
// Apply a custom category to all command-line options so that they are the | |
// only ones displayed. | |
static cl::OptionCategory MyToolCategory("my-tool options"); | |
// CommonOptionsParser declares HelpMessage with a description of the common | |
// command-line options related to the compilation database and input files. | |
// It's nice to have this help message in all tools. | |
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage); | |
// A help message for this specific tool can be added afterwards. | |
static cl::extrahelp MoreHelp("\nMore help text...\n"); | |
int main(int argc, const char** argv) | |
{ | |
CommonOptionsParser OptionsParser(argc, argv, MyToolCategory); | |
auto& comp = OptionsParser.getCompilations(); | |
ClangTool tool(comp, OptionsParser.getSourcePathList()); | |
return tool.run(newFrontendActionFactory<Action>().get()); | |
// clang::SyntaxOnlyAction | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment