IndexTypeSourceInfo.cpp revision f8490eeb966103516da4e3ecb05e1a36b3e6e3ec
1//===- CIndexHigh.cpp - Higher level API functions ------------------------===//
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 "IndexingContext.h"
11
12#include "clang/AST/RecursiveASTVisitor.h"
13
14using namespace clang;
15using namespace cxindex;
16
17namespace {
18
19class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
20  IndexingContext &IndexCtx;
21  const NamedDecl *Parent;
22  const DeclContext *ParentDC;
23
24public:
25  TypeIndexer(IndexingContext &indexCtx, const NamedDecl *parent,
26              const DeclContext *DC)
27    : IndexCtx(indexCtx), Parent(parent), ParentDC(DC) { }
28
29  bool shouldWalkTypesOfTypeLocs() const { return false; }
30
31  bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
32    IndexCtx.handleReference(TL.getTypedefNameDecl(), TL.getNameLoc(),
33                             Parent, ParentDC);
34    return true;
35  }
36
37  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
38    IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
39    return true;
40  }
41
42  bool VisitTagTypeLoc(TagTypeLoc TL) {
43    TagDecl *D = TL.getDecl();
44    if (D->getParentFunctionOrMethod())
45      return true;
46
47    if (TL.isDefinition()) {
48      IndexCtx.indexTagDecl(D);
49      return true;
50    }
51
52    if (D->getLocation() == TL.getNameLoc())
53      IndexCtx.handleTagDecl(D);
54    else
55      IndexCtx.handleReference(D, TL.getNameLoc(),
56                               Parent, ParentDC);
57    return true;
58  }
59
60  bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
61    IndexCtx.handleReference(TL.getIFaceDecl(), TL.getNameLoc(),
62                             Parent, ParentDC);
63    return true;
64  }
65
66  bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
67    for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) {
68      IndexCtx.handleReference(TL.getProtocol(i), TL.getProtocolLoc(i),
69                               Parent, ParentDC);
70    }
71    return true;
72  }
73
74  bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
75    if (const TemplateSpecializationType *T = TL.getTypePtr()) {
76      if (IndexCtx.shouldIndexImplicitTemplateInsts()) {
77        if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
78          IndexCtx.handleReference(RD, TL.getTemplateNameLoc(),
79                                   Parent, ParentDC);
80      } else {
81        if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl())
82          IndexCtx.handleReference(D, TL.getTemplateNameLoc(),
83                                   Parent, ParentDC);
84      }
85    }
86    return true;
87  }
88
89  bool TraverseStmt(Stmt *S) {
90    IndexCtx.indexBody(S, Parent, ParentDC);
91    return true;
92  }
93};
94
95} // anonymous namespace
96
97void IndexingContext::indexTypeSourceInfo(TypeSourceInfo *TInfo,
98                                          const NamedDecl *Parent,
99                                          const DeclContext *DC) {
100  if (!TInfo || TInfo->getTypeLoc().isNull())
101    return;
102
103  indexTypeLoc(TInfo->getTypeLoc(), Parent, DC);
104}
105
106void IndexingContext::indexTypeLoc(TypeLoc TL,
107                                   const NamedDecl *Parent,
108                                   const DeclContext *DC) {
109  if (TL.isNull())
110    return;
111
112  if (DC == 0)
113    DC = Parent->getLexicalDeclContext();
114  TypeIndexer(*this, Parent, DC).TraverseTypeLoc(TL);
115}
116
117void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
118                                                  const NamedDecl *Parent,
119                                                  const DeclContext *DC) {
120  if (!NNS)
121    return;
122
123  if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
124    indexNestedNameSpecifierLoc(Prefix, Parent, DC);
125
126  if (DC == 0)
127    DC = Parent->getLexicalDeclContext();
128  SourceLocation Loc = NNS.getSourceRange().getBegin();
129
130  switch (NNS.getNestedNameSpecifier()->getKind()) {
131  case NestedNameSpecifier::Identifier:
132  case NestedNameSpecifier::Global:
133    break;
134
135  case NestedNameSpecifier::Namespace:
136    handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(),
137                    Loc, Parent, DC);
138    break;
139  case NestedNameSpecifier::NamespaceAlias:
140    handleReference(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(),
141                    Loc, Parent, DC);
142    break;
143
144  case NestedNameSpecifier::TypeSpec:
145  case NestedNameSpecifier::TypeSpecWithTemplate:
146    indexTypeLoc(NNS.getTypeLoc(), Parent, DC);
147    break;
148  }
149}
150
151void IndexingContext::indexTagDecl(const TagDecl *D) {
152  if (handleTagDecl(D)) {
153    if (D->isThisDeclarationADefinition())
154      indexDeclContext(D);
155  }
156}
157