• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
PrintIndexDataConsumer(raw_ostream & OS)67   PrintIndexDataConsumer(raw_ostream &OS) : OS(OS) {
68   }
69 
initialize(ASTContext & Ctx)70   void initialize(ASTContext &Ctx) override {
71     CGNameGen.reset(new CodegenNameGenerator(Ctx));
72   }
73 
handleDeclOccurence(const Decl * D,SymbolRoleSet Roles,ArrayRef<SymbolRelation> Relations,FileID FID,unsigned Offset,ASTNodeInfo ASTNode)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 
handleModuleOccurence(const ImportDecl * ImportD,SymbolRoleSet Roles,FileID FID,unsigned Offset)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 
printSourceSymbols(ArrayRef<const char * > Args)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 
printSymbolInfo(SymbolInfo SymInfo,raw_ostream & OS)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 
printSymbolNameAndUSR(const Decl * D,ASTContext & Ctx,raw_ostream & OS)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 
indextest_core_main(int argc,const char ** argv)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