1//===-- core_main.cpp - Core Index Tool testbed ---------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "clang/Frontend/ASTUnit.h" 11#include "clang/Frontend/CompilerInstance.h" 12#include "clang/Frontend/CompilerInvocation.h" 13#include "clang/Frontend/FrontendAction.h" 14#include "clang/Index/IndexingAction.h" 15#include "clang/Index/IndexDataConsumer.h" 16#include "clang/Index/USRGeneration.h" 17#include "clang/Index/CodegenNameGenerator.h" 18#include "llvm/Support/CommandLine.h" 19#include "llvm/Support/Signals.h" 20#include "llvm/Support/raw_ostream.h" 21#include "llvm/Support/PrettyStackTrace.h" 22 23using namespace clang; 24using namespace clang::index; 25using namespace llvm; 26 27extern "C" int indextest_core_main(int argc, const char **argv); 28 29namespace { 30 31enum class ActionType { 32 None, 33 PrintSourceSymbols, 34}; 35 36namespace options { 37 38static cl::OptionCategory IndexTestCoreCategory("index-test-core options"); 39 40static cl::opt<ActionType> 41Action(cl::desc("Action:"), cl::init(ActionType::None), 42 cl::values( 43 clEnumValN(ActionType::PrintSourceSymbols, 44 "print-source-symbols", "Print symbols from source"), 45 clEnumValEnd), 46 cl::cat(IndexTestCoreCategory)); 47 48static cl::extrahelp MoreHelp( 49 "\nAdd \"-- <compiler arguments>\" at the end to setup the compiler " 50 "invocation\n" 51); 52 53} 54} // anonymous namespace 55 56static void printSymbolInfo(SymbolInfo SymInfo, raw_ostream &OS); 57static void printSymbolNameAndUSR(const Decl *D, ASTContext &Ctx, 58 raw_ostream &OS); 59 60namespace { 61 62class PrintIndexDataConsumer : public IndexDataConsumer { 63 raw_ostream &OS; 64 std::unique_ptr<CodegenNameGenerator> CGNameGen; 65 66public: 67 PrintIndexDataConsumer(raw_ostream &OS) : OS(OS) { 68 } 69 70 void initialize(ASTContext &Ctx) override { 71 CGNameGen.reset(new CodegenNameGenerator(Ctx)); 72 } 73 74 bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles, 75 ArrayRef<SymbolRelation> Relations, 76 FileID FID, unsigned Offset, 77 ASTNodeInfo ASTNode) override { 78 ASTContext &Ctx = D->getASTContext(); 79 SourceManager &SM = Ctx.getSourceManager(); 80 81 unsigned Line = SM.getLineNumber(FID, Offset); 82 unsigned Col = SM.getColumnNumber(FID, Offset); 83 OS << Line << ':' << Col << " | "; 84 85 printSymbolInfo(getSymbolInfo(D), OS); 86 OS << " | "; 87 88 printSymbolNameAndUSR(D, Ctx, OS); 89 OS << " | "; 90 91 if (CGNameGen->writeName(D, OS)) 92 OS << "<no-cgname>"; 93 OS << " | "; 94 95 printSymbolRoles(Roles, OS); 96 OS << " | "; 97 98 OS << "rel: " << Relations.size() << '\n'; 99 100 for (auto &SymRel : Relations) { 101 OS << '\t'; 102 printSymbolRoles(SymRel.Roles, OS); 103 OS << " | "; 104 printSymbolNameAndUSR(SymRel.RelatedSymbol, Ctx, OS); 105 OS << '\n'; 106 } 107 108 return true; 109 } 110 111 bool handleModuleOccurence(const ImportDecl *ImportD, SymbolRoleSet Roles, 112 FileID FID, unsigned Offset) override { 113 ASTContext &Ctx = ImportD->getASTContext(); 114 SourceManager &SM = Ctx.getSourceManager(); 115 116 unsigned Line = SM.getLineNumber(FID, Offset); 117 unsigned Col = SM.getColumnNumber(FID, Offset); 118 OS << Line << ':' << Col << " | "; 119 120 printSymbolInfo(getSymbolInfo(ImportD), OS); 121 OS << " | "; 122 123 OS << ImportD->getImportedModule()->getFullModuleName() << " | "; 124 125 printSymbolRoles(Roles, OS); 126 OS << " |\n"; 127 128 return true; 129 } 130}; 131 132} // anonymous namespace 133 134//===----------------------------------------------------------------------===// 135// Print Source Symbols 136//===----------------------------------------------------------------------===// 137 138static bool printSourceSymbols(ArrayRef<const char *> Args) { 139 SmallVector<const char *, 4> ArgsWithProgName; 140 ArgsWithProgName.push_back("clang"); 141 ArgsWithProgName.append(Args.begin(), Args.end()); 142 IntrusiveRefCntPtr<DiagnosticsEngine> 143 Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions)); 144 IntrusiveRefCntPtr<CompilerInvocation> 145 CInvok(createInvocationFromCommandLine(ArgsWithProgName, Diags)); 146 if (!CInvok) 147 return true; 148 149 auto DataConsumer = std::make_shared<PrintIndexDataConsumer>(outs()); 150 IndexingOptions IndexOpts; 151 std::unique_ptr<FrontendAction> IndexAction; 152 IndexAction = createIndexingAction(DataConsumer, IndexOpts, 153 /*WrappedAction=*/nullptr); 154 155 auto PCHContainerOps = std::make_shared<PCHContainerOperations>(); 156 std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction( 157 CInvok.get(), PCHContainerOps, Diags, IndexAction.get())); 158 159 if (!Unit) 160 return true; 161 162 return false; 163} 164 165//===----------------------------------------------------------------------===// 166// Helper Utils 167//===----------------------------------------------------------------------===// 168 169static void printSymbolInfo(SymbolInfo SymInfo, raw_ostream &OS) { 170 OS << getSymbolKindString(SymInfo.Kind); 171 if (SymInfo.SubKinds) { 172 OS << '('; 173 printSymbolSubKinds(SymInfo.SubKinds, OS); 174 OS << ')'; 175 } 176 OS << '/' << getSymbolLanguageString(SymInfo.Lang); 177} 178 179static void printSymbolNameAndUSR(const Decl *D, ASTContext &Ctx, 180 raw_ostream &OS) { 181 if (printSymbolName(D, Ctx.getLangOpts(), OS)) { 182 OS << "<no-name>"; 183 } 184 OS << " | "; 185 186 SmallString<256> USRBuf; 187 if (generateUSRForDecl(D, USRBuf)) { 188 OS << "<no-usr>"; 189 } else { 190 OS << USRBuf; 191 } 192} 193 194//===----------------------------------------------------------------------===// 195// Command line processing. 196//===----------------------------------------------------------------------===// 197 198int indextest_core_main(int argc, const char **argv) { 199 sys::PrintStackTraceOnErrorSignal(argv[0]); 200 PrettyStackTraceProgram X(argc, argv); 201 202 assert(argv[1] == StringRef("core")); 203 ++argv; 204 --argc; 205 206 std::vector<const char *> CompArgs; 207 const char **DoubleDash = std::find(argv, argv + argc, StringRef("--")); 208 if (DoubleDash != argv + argc) { 209 CompArgs = std::vector<const char *>(DoubleDash + 1, argv + argc); 210 argc = DoubleDash - argv; 211 } 212 213 cl::HideUnrelatedOptions(options::IndexTestCoreCategory); 214 cl::ParseCommandLineOptions(argc, argv, "index-test-core"); 215 216 if (options::Action == ActionType::None) { 217 errs() << "error: action required; pass '-help' for options\n"; 218 return 1; 219 } 220 221 if (options::Action == ActionType::PrintSourceSymbols) { 222 if (CompArgs.empty()) { 223 errs() << "error: missing compiler args; pass '-- <compiler arguments>'\n"; 224 return 1; 225 } 226 return printSourceSymbols(CompArgs); 227 } 228 229 return 0; 230} 231