From 806faaf42ba49fffaa9217c368d53bddd7e4fcf1 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Tue, 25 Oct 2016 21:11:22 +0000 Subject: [PATCH] [index] Fixes for locations and relations in Objective C categories and 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 llvm-svn: 285120 --- clang/include/clang/Index/IndexSymbol.h | 4 ++- clang/lib/Index/IndexDecl.cpp | 46 ++++++++++++++++++++----- clang/lib/Index/IndexSymbol.cpp | 4 +++ clang/test/Index/Core/index-source.m | 24 +++++++++++++ clang/test/Index/Core/index-subkinds.m | 10 ++++-- 5 files changed, 75 insertions(+), 13 deletions(-) diff --git a/clang/include/clang/Index/IndexSymbol.h b/clang/include/clang/Index/IndexSymbol.h index b0bc93e464b4..d539b4903b79 100644 --- a/clang/include/clang/Index/IndexSymbol.h +++ b/clang/include/clang/Index/IndexSymbol.h @@ -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. diff --git a/clang/lib/Index/IndexDecl.cpp b/clang/lib/Index/IndexDecl.cpp index eb3e15114735..1225391dc2a6 100644 --- a/clang/lib/Index/IndexDecl.cpp +++ b/clang/lib/Index/IndexDecl.cpp @@ -75,8 +75,21 @@ public: } } - bool handleObjCMethod(const ObjCMethodDecl *D) { - if (!IndexCtx.handleDecl(D, (unsigned)SymbolRole::Dynamic)) + bool handleObjCMethod(const ObjCMethodDecl *D, + const ObjCPropertyDecl *AssociatedProp = nullptr) { + SmallVector Relations; + SmallVector 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()) @@ -269,9 +282,18 @@ public: } 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; } @@ -279,8 +301,14 @@ public: 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; @@ -299,10 +327,10 @@ public: 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); diff --git a/clang/lib/Index/IndexSymbol.cpp b/clang/lib/Index/IndexSymbol.cpp index 13a845230072..65f5241037c2 100644 --- a/clang/lib/Index/IndexSymbol.cpp +++ b/clang/lib/Index/IndexSymbol.cpp @@ -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 } @@ -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; } }); } diff --git a/clang/test/Index/Core/index-source.m b/clang/test/Index/Core/index-source.m index 2e9c01c02d48..554378ea3cf7 100644 --- a/clang/test/Index/Core/index-source.m +++ b/clang/test/Index/Core/index-source.m @@ -95,13 +95,37 @@ extern int setjmp(jmp_buf); @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 | | Def | rel: 0 @implementation I3 // CHECK: [[@LINE+3]]:13 | instance-property/ObjC | prop | c:objc(cs)I3(py)prop | | 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 | | Decl | rel: 0 +// CHECK: [[@LINE+2]]:21 | protocol/ObjC | Prot1 | c:objc(pl)Prot1 | | Ref,RelBase | rel: 1 +// CHECK-NEXT: RelBase | bar | c:objc(cy)I3@bar +@interface I3(bar) +@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 | | Def | rel: 0 +@implementation I3(bar) +@end + +// CHECK: [[@LINE+1]]:12 | extension/ObjC | | | | Decl | rel: 0 +@interface NonExistent() +@end diff --git a/clang/test/Index/Core/index-subkinds.m b/clang/test/Index/Core/index-subkinds.m index e668d84ffa89..a83da03c3de8 100644 --- a/clang/test/Index/Core/index-subkinds.m +++ b/clang/test/Index/Core/index-subkinds.m @@ -26,10 +26,13 @@ -(void)testIt2 {} @end -// CHECK: [[@LINE+1]]:12 | extension/ObjC | cat | c:objc(cy)MyTestCase@cat | | 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 | | Decl | rel: 0 @interface MyTestCase(cat) @end -// CHECK: [[@LINE+1]]:17 | extension/ObjC | MyTestCase | c:objc(cy)MyTestCase@cat | | 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 | | 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 {} @@ -38,7 +41,8 @@ @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 | | 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 | | Decl,RelChild | rel: 1