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