Skip to content

Commit

Permalink
[index] Fixes for locations and relations in Objective C categories a…
Browse files Browse the repository at this point in the history
…nd getters/setters

- Add entries for protocols on categories
- Add relation between categories and class they extend
- Add relation between getters/setters and their corresponding property
- Use category name location as the location of category decls/defs if it has one

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@285120 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
akyrtzi committed Oct 25, 2016
1 parent 77bc8ef commit 5692230
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 13 deletions.
4 changes: 3 additions & 1 deletion include/clang/Index/IndexSymbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,10 @@ enum class SymbolRole : uint16_t {
RelationOverrideOf = 1 << 11,
RelationReceivedBy = 1 << 12,
RelationCalledBy = 1 << 13,
RelationExtendedBy = 1 << 14,
RelationAccessorOf = 1 << 15,
};
static const unsigned SymbolRoleBitNum = 14;
static const unsigned SymbolRoleBitNum = 16;
typedef unsigned SymbolRoleSet;

/// Represents a relation to another symbol for a symbol occurrence.
Expand Down
46 changes: 37 additions & 9 deletions lib/Index/IndexDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,21 @@ class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
}
}

bool handleObjCMethod(const ObjCMethodDecl *D) {
if (!IndexCtx.handleDecl(D, (unsigned)SymbolRole::Dynamic))
bool handleObjCMethod(const ObjCMethodDecl *D,
const ObjCPropertyDecl *AssociatedProp = nullptr) {
SmallVector<SymbolRelation, 4> Relations;
SmallVector<const ObjCMethodDecl*, 4> Overriden;

D->getOverriddenMethods(Overriden);
for(auto overridden: Overriden) {
Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf,
overridden);
}
if (AssociatedProp)
Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf,
AssociatedProp);

if (!IndexCtx.handleDecl(D, (unsigned)SymbolRole::Dynamic, Relations))
return false;
IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D);
for (const auto *I : D->parameters())
Expand Down Expand Up @@ -269,18 +282,33 @@ class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
}

bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
if (!IndexCtx.handleDecl(D))
return false;
IndexCtx.indexDeclContext(D);
const ObjCInterfaceDecl *C = D->getClassInterface();
if (C)
TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
SymbolRoleSet(), SymbolRelation{
(unsigned)SymbolRole::RelationExtendedBy, D
}));
SourceLocation CategoryLoc = D->getCategoryNameLoc();
if (!CategoryLoc.isValid())
CategoryLoc = D->getLocation();
TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));
TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D));
TRY_TO(IndexCtx.indexDeclContext(D));
return true;
}

bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
const ObjCCategoryDecl *Cat = D->getCategoryDecl();
if (!Cat)
return true;

if (!IndexCtx.handleDecl(D))
const ObjCInterfaceDecl *C = D->getClassInterface();
if (C)
TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
SymbolRoleSet()));
SourceLocation CategoryLoc = D->getCategoryNameLoc();
if (!CategoryLoc.isValid())
CategoryLoc = D->getLocation();
if (!IndexCtx.handleDecl(D, CategoryLoc))
return false;
IndexCtx.indexDeclContext(D);
return true;
Expand All @@ -299,10 +327,10 @@ class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
handleObjCMethod(MD);
handleObjCMethod(MD, D);
if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
handleObjCMethod(MD);
handleObjCMethod(MD, D);
if (!IndexCtx.handleDecl(D))
return false;
IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
Expand Down
4 changes: 4 additions & 0 deletions lib/Index/IndexSymbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ void index::applyForEachSymbolRole(SymbolRoleSet Roles,
APPLY_FOR_ROLE(RelationOverrideOf);
APPLY_FOR_ROLE(RelationReceivedBy);
APPLY_FOR_ROLE(RelationCalledBy);
APPLY_FOR_ROLE(RelationExtendedBy);
APPLY_FOR_ROLE(RelationAccessorOf);

#undef APPLY_FOR_ROLE
}
Expand All @@ -288,6 +290,8 @@ void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) {
case SymbolRole::RelationOverrideOf: OS << "RelOver"; break;
case SymbolRole::RelationReceivedBy: OS << "RelRec"; break;
case SymbolRole::RelationCalledBy: OS << "RelCall"; break;
case SymbolRole::RelationExtendedBy: OS << "RelExt"; break;
case SymbolRole::RelationAccessorOf: OS << "RelAcc"; break;
}
});
}
Expand Down
24 changes: 24 additions & 0 deletions test/Index/Core/index-source.m
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,37 @@ @implementation I2

@interface I3
@property (readwrite) id prop;
// CHECK: [[@LINE+3]]:1 | instance-method/ObjC | prop | c:objc(cs)I3(im)prop | -[I3 prop] | Decl,Dyn,RelChild,RelAcc | rel: 2
// CHECK-NEXT: RelChild | I3 | c:objc(cs)I3
// CHECK-NEXT: RelAcc | prop | c:objc(cs)I3(py)prop
-(id)prop;
// CHECK: [[@LINE+3]]:1 | instance-method/ObjC | setProp: | c:objc(cs)I3(im)setProp: | -[I3 setProp:] | Decl,Dyn,RelChild,RelAcc | rel: 2
// CHECK-NEXT: RelChild | I3 | c:objc(cs)I3
// CHECK-NEXT: RelAcc | prop | c:objc(cs)I3(py)prop
-(void)setProp:(id)p;
@end

// CHECK: [[@LINE+1]]:17 | class/ObjC | I3 | c:objc(cs)I3 | <no-cgname> | Def | rel: 0
@implementation I3
// CHECK: [[@LINE+3]]:13 | instance-property/ObjC | prop | c:objc(cs)I3(py)prop | <no-cgname> | Ref | rel: 0
// CHECK: [[@LINE+2]]:13 | instance-method/ObjC | prop | c:objc(cs)I3(im)prop | -[I3 prop] | Def,RelChild | rel: 1
// CHECK: [[@LINE+1]]:13 | instance-method/ObjC | setProp: | c:objc(cs)I3(im)setProp: | -[I3 setProp:] | Def,RelChild | rel: 1
@synthesize prop = _prop;
@end

// CHECK: [[@LINE+5]]:12 | class/ObjC | I3 | c:objc(cs)I3 | _OBJC_CLASS_$_I3 | Ref,RelExt | rel: 1
// CHECK-NEXT: RelExt | bar | c:objc(cy)I3@bar
// CHECK: [[@LINE+3]]:15 | extension/ObjC | bar | c:objc(cy)I3@bar | <no-cgname> | Decl | rel: 0
// CHECK: [[@LINE+2]]:21 | protocol/ObjC | Prot1 | c:objc(pl)Prot1 | <no-cgname> | Ref,RelBase | rel: 1
// CHECK-NEXT: RelBase | bar | c:objc(cy)I3@bar
@interface I3(bar) <Prot1>
@end

// CHECK: [[@LINE+2]]:17 | class/ObjC | I3 | c:objc(cs)I3 | _OBJC_CLASS_$_I3 | Ref | rel: 0
// CHECK: [[@LINE+1]]:20 | extension/ObjC | I3 | c:objc(cy)I3@bar | <no-cgname> | Def | rel: 0
@implementation I3(bar)
@end

// CHECK: [[@LINE+1]]:12 | extension/ObjC | <no-name> | <no-usr> | <no-cgname> | Decl | rel: 0
@interface NonExistent()
@end
10 changes: 7 additions & 3 deletions test/Index/Core/index-subkinds.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,13 @@ @implementation SubTestCase
-(void)testIt2 {}
@end

// CHECK: [[@LINE+1]]:12 | extension/ObjC | cat | c:objc(cy)MyTestCase@cat | <no-cgname> | Decl | rel: 0
// CHECK: [[@LINE+3]]:12 | class(test)/ObjC | MyTestCase | c:objc(cs)MyTestCase | _OBJC_CLASS_$_MyTestCase | Ref,RelExt | rel: 1
// CHECK-NEXT: RelExt | cat | c:objc(cy)MyTestCase@cat
// CHECK: [[@LINE+1]]:23 | extension/ObjC | cat | c:objc(cy)MyTestCase@cat | <no-cgname> | Decl | rel: 0
@interface MyTestCase(cat)
@end
// CHECK: [[@LINE+1]]:17 | extension/ObjC | MyTestCase | c:objc(cy)MyTestCase@cat | <no-cgname> | Def | rel: 0
// CHECK: [[@LINE+2]]:17 | class(test)/ObjC | MyTestCase | c:objc(cs)MyTestCase | _OBJC_CLASS_$_MyTestCase | Ref | rel: 0
// CHECK: [[@LINE+1]]:28 | extension/ObjC | MyTestCase | c:objc(cy)MyTestCase@cat | <no-cgname> | Def | rel: 0
@implementation MyTestCase(cat)
// CHECK: [[@LINE+1]]:1 | instance-method(test)/ObjC | testInCat | c:objc(cs)MyTestCase(im)testInCat | -[MyTestCase(cat) testInCat] | Def,Dyn,RelChild | rel: 1
- (void)testInCat {}
Expand All @@ -38,7 +41,8 @@ - (void)testInCat {}

@class NSButton;
@interface IBCls
// CHECK: [[@LINE+2]]:34 | instance-method/ObjC | prop | c:objc(cs)IBCls(im)prop | -[IBCls prop] | Decl,Dyn,RelChild | rel: 1

// CHECK: [[@LINE+2]]:34 | instance-method/ObjC | prop | c:objc(cs)IBCls(im)prop | -[IBCls prop] | Decl,Dyn,RelChild,RelAcc | rel: 2
// CHECK: [[@LINE+1]]:34 | instance-property(IB)/ObjC | prop | c:objc(cs)IBCls(py)prop | <no-cgname> | Decl,RelChild | rel: 1
@property (readonly) IBOutlet id prop;
// CHECK: [[@LINE+1]]:54 | instance-property(IB,IBColl)/ObjC | propColl | c:objc(cs)IBCls(py)propColl | <no-cgname> | Decl,RelChild | rel: 1
Expand Down

0 comments on commit 5692230

Please sign in to comment.