CTagsEmitter.cpp revision 314564
1228753Smm//===- CTagsEmitter.cpp - Generate ctags-compatible index ------------------===// 2228753Smm// 3228753Smm// The LLVM Compiler Infrastructure 4228753Smm// 5228753Smm// This file is distributed under the University of Illinois Open Source 6228753Smm// License. See LICENSE.TXT for details. 7228753Smm// 8228753Smm//===----------------------------------------------------------------------===// 9228753Smm// 10228753Smm// This tablegen backend emits an index of definitions in ctags(1) format. 11228753Smm// A helper script, utils/TableGen/tdtags, provides an easier-to-use 12228753Smm// interface; run 'tdtags -H' for documentation. 13228753Smm// 14228753Smm//===----------------------------------------------------------------------===// 15228753Smm 16228753Smm#include "llvm/Support/SourceMgr.h" 17228753Smm#include "llvm/Support/MemoryBuffer.h" 18228753Smm#include "llvm/TableGen/Error.h" 19228753Smm#include "llvm/TableGen/Record.h" 20228753Smm#include <algorithm> 21228753Smm#include <string> 22228753Smm#include <vector> 23228753Smmusing namespace llvm; 24228753Smm 25228763Smm#define DEBUG_TYPE "ctags-emitter" 26228753Smm 27353377Smmnamespace { 28228773Smm 29228753Smmclass Tag { 30228753Smmprivate: 31228753Smm const std::string *Id; 32353377Smm SMLoc Loc; 33228753Smmpublic: 34228753Smm Tag(const std::string &Name, const SMLoc Location) 35228753Smm : Id(&Name), Loc(Location) {} 36228753Smm int operator<(const Tag &B) const { return *Id < *B.Id; } 37228753Smm void emit(raw_ostream &OS) const { 38228753Smm const MemoryBuffer *CurMB = 39228753Smm SrcMgr.getMemoryBuffer(SrcMgr.FindBufferContainingLoc(Loc)); 40228753Smm auto BufferName = CurMB->getBufferIdentifier(); 41315433Smm std::pair<unsigned, unsigned> LineAndColumn = SrcMgr.getLineAndColumn(Loc); 42228753Smm OS << *Id << "\t" << BufferName << "\t" << LineAndColumn.first << "\n"; 43238856Smm } 44238856Smm}; 45228753Smm 46228753Smmclass CTagsEmitter { 47228753Smmprivate: 48228753Smm RecordKeeper &Records; 49228753Smmpublic: 50353377Smm CTagsEmitter(RecordKeeper &R) : Records(R) {} 51353377Smm 52228753Smm void run(raw_ostream &OS); 53228753Smm 54228753Smmprivate: 55228753Smm static SMLoc locate(const Record *R); 56228753Smm}; 57313571Smm 58228753Smm} // End anonymous namespace. 59313571Smm 60228753SmmSMLoc CTagsEmitter::locate(const Record *R) { 61228753Smm ArrayRef<SMLoc> Locs = R->getLoc(); 62228753Smm return !Locs.empty() ? Locs.front() : SMLoc(); 63228753Smm} 64228753Smm 65228753Smmvoid CTagsEmitter::run(raw_ostream &OS) { 66228753Smm const auto &Classes = Records.getClasses(); 67228753Smm const auto &Defs = Records.getDefs(); 68228753Smm std::vector<Tag> Tags; 69228753Smm // Collect tags. 70228753Smm Tags.reserve(Classes.size() + Defs.size()); 71228753Smm for (const auto &C : Classes) 72228753Smm Tags.push_back(Tag(C.first, locate(C.second.get()))); 73228753Smm for (const auto &D : Defs) 74228753Smm Tags.push_back(Tag(D.first, locate(D.second.get()))); 75228753Smm // Emit tags. 76228753Smm std::sort(Tags.begin(), Tags.end()); 77228753Smm OS << "!_TAG_FILE_FORMAT\t1\t/original ctags format/\n"; 78228753Smm OS << "!_TAG_FILE_SORTED\t1\t/0=unsorted, 1=sorted, 2=foldcase/\n"; 79228753Smm for (const Tag &T : Tags) 80228753Smm T.emit(OS); 81228753Smm} 82228753Smm 83228753Smmnamespace llvm { 84228753Smm 85228753Smmvoid EmitCTags(RecordKeeper &RK, raw_ostream &OS) { CTagsEmitter(RK).run(OS); } 86228753Smm 87228753Smm} // End llvm namespace. 88228753Smm