Home | History | Annotate | Download | only in c-index-test
      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 
     23 using namespace clang;
     24 using namespace clang::index;
     25 using namespace llvm;
     26 
     27 extern "C" int indextest_core_main(int argc, const char **argv);
     28 
     29 namespace {
     30 
     31 enum class ActionType {
     32   None,
     33   PrintSourceSymbols,
     34 };
     35 
     36 namespace options {
     37 
     38 static cl::OptionCategory IndexTestCoreCategory("index-test-core options");
     39 
     40 static cl::opt<ActionType>
     41 Action(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 
     48 static cl::extrahelp MoreHelp(
     49   "\nAdd \"-- <compiler arguments>\" at the end to setup the compiler "
     50   "invocation\n"
     51 );
     52 
     53 }
     54 } // anonymous namespace
     55 
     56 static void printSymbolInfo(SymbolInfo SymInfo, raw_ostream &OS);
     57 static void printSymbolNameAndUSR(const Decl *D, ASTContext &Ctx,
     58                                   raw_ostream &OS);
     59 
     60 namespace {
     61 
     62 class PrintIndexDataConsumer : public IndexDataConsumer {
     63   raw_ostream &OS;
     64   std::unique_ptr<CodegenNameGenerator> CGNameGen;
     65 
     66 public:
     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 
    138 static 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 
    169 static 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 
    179 static 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 
    198 int 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