diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h --- a/clang/include/clang/ExtractAPI/API.h +++ b/clang/include/clang/ExtractAPI/API.h @@ -71,6 +71,7 @@ RK_ObjCInstanceMethod, RK_ObjCInterface, RK_ObjCCategory, + RK_ObjCCategoryModule, RK_ObjCProtocol, RK_MacroDefinition, RK_Typedef, @@ -144,6 +145,9 @@ Comment(Comment), Declaration(Declaration), SubHeading(SubHeading), IsFromSystemHeader(IsFromSystemHeader), Kind(Kind) {} + APIRecord(RecordKind Kind, StringRef USR, StringRef Name) + : USR(USR), Name(Name), Kind(Kind) {} + // Pure virtual destructor to make APIRecord abstract virtual ~APIRecord() = 0; }; @@ -488,11 +492,24 @@ virtual void anchor(); }; +struct ObjCCategoryModuleRecord : APIRecord { + // ObjCCategoryRecord%s are stored in and owned by APISet. + SmallVector Categories; + + ObjCCategoryModuleRecord(StringRef USR, StringRef Name) + : APIRecord(RK_ObjCCategoryModule, USR, Name) {} + + static bool classof(const APIRecord *Record) { + return Record->getKind() == RK_ObjCCategoryModule; + } + +private: + virtual void anchor(); +}; + /// This holds information associated with Objective-C interfaces/classes. struct ObjCInterfaceRecord : ObjCContainerRecord { SymbolReference SuperClass; - // ObjCCategoryRecord%s are stored in and owned by APISet. - SmallVector Categories; ObjCInterfaceRecord(StringRef USR, StringRef Name, PresumedLoc Loc, AvailabilitySet Availabilities, LinkageInfo Linkage, @@ -668,6 +685,9 @@ DeclarationFragments SubHeading, bool IsFromSystemHeader); + ObjCCategoryModuleRecord *addObjCCategoryModule(StringRef Name, + StringRef USR); + /// Create and add an Objective-C category record into the API set. /// /// Note: the caller is responsible for keeping the StringRef \p Name and @@ -679,7 +699,7 @@ AvailabilitySet Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, SymbolReference Interface, - bool IsFromSystemHeader); + bool IsFromSystemHeader, bool IsFromExternalModule); /// Create and add an Objective-C interface record into the API set. /// @@ -795,6 +815,9 @@ const RecordMap &getObjCCategories() const { return ObjCCategories; } + const RecordMap &getObjCCategoryModule() const { + return ObjCCategoryModule; + } const RecordMap &getObjCInterfaces() const { return ObjCInterfaces; } @@ -848,6 +871,7 @@ RecordMap Enums; RecordMap Structs; RecordMap ObjCCategories; + RecordMap ObjCCategoryModule; RecordMap ObjCInterfaces; RecordMap ObjCProtocols; RecordMap Macros; diff --git a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h --- a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h +++ b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h @@ -484,9 +484,13 @@ SymbolReference Interface(InterfaceDecl->getName(), API.recordUSR(InterfaceDecl)); + if (isInSystemHeader(InterfaceDecl)) + API.addObjCCategoryModule(InterfaceDecl->getName(), + API.recordUSR(InterfaceDecl)); + ObjCCategoryRecord *ObjCCategoryRecord = API.addObjCCategory( Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration, SubHeading, - Interface, isInSystemHeader(Decl)); + Interface, isInSystemHeader(Decl), isInSystemHeader(InterfaceDecl)); getDerivedExtractAPIVisitor().recordObjCMethods(ObjCCategoryRecord, Decl->methods()); diff --git a/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h b/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h --- a/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h +++ b/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h @@ -35,6 +35,10 @@ getDerived()->traverseObjCProtocols(); + getDerived()->traverseObjCCategories(); + + getDerived()->traverseObjCCategoryModule(); + getDerived()->traverseMacroDefinitionRecords(); getDerived()->traverseTypedefRecords(); @@ -70,6 +74,16 @@ getDerived()->visitObjCContainerRecord(*Protocol.second); } + void traverseObjCCategories() { + for (const auto &Category : API.getObjCCategories()) + getDerived()->visitObjCCategoryRecord(*Category.second); + } + + void traverseObjCCategoryModule() { + for (const auto &CategoryModule : API.getObjCCategoryModule()) + getDerived()->visitObjCCategoryModuleRecord(*CategoryModule.second); + } + void traverseMacroDefinitionRecords() { for (const auto &Macro : API.getMacros()) getDerived()->visitMacroDefinitionRecord(*Macro.second); @@ -95,6 +109,12 @@ /// Visit an Objective-C container record. void visitObjCContainerRecord(const ObjCContainerRecord &Record){}; + /// Visit an Objective-C category record. + void visitObjCCategoryRecord(const ObjCCategoryRecord &Record){}; + + /// Visit an Objective-C category module record. + void visitObjCCategoryModuleRecord(const ObjCCategoryModuleRecord &Record){}; + /// Visit a macro definition record. void visitMacroDefinitionRecord(const MacroDefinitionRecord &Record){}; diff --git a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h --- a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h +++ b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h @@ -163,6 +163,12 @@ /// Visit an Objective-C container record. void visitObjCContainerRecord(const ObjCContainerRecord &Record); + /// Visit an Objective-C category record. + void visitObjCCategoryRecord(const ObjCCategoryRecord &Record); + + /// Visit an Objective-C category module record. + void visitObjCCategoryModuleRecord(const ObjCCategoryModuleRecord &Record); + /// Visit a macro definition record. void visitMacroDefinitionRecord(const MacroDefinitionRecord &Record); diff --git a/clang/lib/ExtractAPI/API.cpp b/clang/lib/ExtractAPI/API.cpp --- a/clang/lib/ExtractAPI/API.cpp +++ b/clang/lib/ExtractAPI/API.cpp @@ -120,22 +120,34 @@ SubHeading, IsFromSystemHeader); } +ObjCCategoryModuleRecord *APISet::addObjCCategoryModule(StringRef Name, + StringRef USR) { + // Create the category record. + auto *Record = + addTopLevelRecord(USRBasedLookupTable, ObjCCategoryModule, USR, Name); + + return Record; +} + ObjCCategoryRecord *APISet::addObjCCategory( StringRef Name, StringRef USR, PresumedLoc Loc, AvailabilitySet Availabilities, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, - SymbolReference Interface, bool IsFromSystemHeader) { + SymbolReference Interface, bool IsFromSystemHeader, + bool IsFromExternalModule) { // Create the category record. auto *Record = addTopLevelRecord(USRBasedLookupTable, ObjCCategories, USR, Name, Loc, std::move(Availabilities), Comment, Declaration, SubHeading, Interface, IsFromSystemHeader); - // If this category is extending a known interface, associate it with the - // ObjCInterfaceRecord. - auto It = ObjCInterfaces.find(Interface.USR); - if (It != ObjCInterfaces.end()) - It->second->Categories.push_back(Record); + // If this category is extending an external module, associate it with that + // module. + if (IsFromExternalModule) { + auto It = ObjCCategoryModule.find(Interface.USR); + if (It != ObjCCategoryModule.end()) + It->second->Categories.push_back(Record); + } return Record; } @@ -298,6 +310,7 @@ void ObjCInstanceMethodRecord::anchor() {} void ObjCClassMethodRecord::anchor() {} void ObjCCategoryRecord::anchor() {} +void ObjCCategoryModuleRecord::anchor() {} void ObjCInterfaceRecord::anchor() {} void ObjCProtocolRecord::anchor() {} void MacroDefinitionRecord::anchor() {} diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -319,7 +319,13 @@ /// Objective-C methods). Can be used as sub-headings for documentation. Object serializeNames(const APIRecord &Record) { Object Names; - Names["title"] = Record.Name; + if (auto *CategoryRecord = + dyn_cast_or_null(&Record)) + Names["title"] = + (CategoryRecord->Interface.Name + " (" + Record.Name + ")").str(); + else + Names["title"] = Record.Name; + serializeArray(Names, "subHeading", serializeDeclarationFragments(Record.SubHeading)); DeclarationFragments NavigatorFragments; @@ -391,9 +397,12 @@ Kind["displayName"] = "Class"; break; case APIRecord::RK_ObjCCategory: - // We don't serialize out standalone Objective-C category symbols yet. - llvm_unreachable("Serializing standalone Objective-C category symbols is " - "not supported."); + Kind["identifier"] = AddLangPrefix("class.extension"); + Kind["displayName"] = "Class Extension"; + break; + case APIRecord::RK_ObjCCategoryModule: + Kind["identifier"] = AddLangPrefix("module.extension"); + Kind["displayName"] = "Module Extension"; break; case APIRecord::RK_ObjCProtocol: Kind["identifier"] = AddLangPrefix("protocol"); @@ -497,16 +506,6 @@ if (!ParentRecord) ParentRecord = API.findRecordForUSR(CurrentParent->ParentUSR); - // If the parent is a category then we need to pretend this belongs to the - // associated interface. - if (auto *CategoryRecord = - dyn_cast_or_null(ParentRecord)) { - ParentRecord = API.findRecordForUSR(CategoryRecord->Interface.USR); - CurrentParentComponent = PathComponent(CategoryRecord->Interface.USR, - CategoryRecord->Interface.Name, - APIRecord::RK_ObjCInterface); - } - // The parent record doesn't exist which means the symbol shouldn't be // treated as part of the current product. if (!ParentRecord) { @@ -720,19 +719,41 @@ // record that Record is inherited from SuperClass. serializeRelationship(RelationshipKind::InheritsFrom, Record, ObjCInterface->SuperClass); + } +} - // Members of categories extending an interface are serialized as members of - // the interface. - for (const auto *Category : ObjCInterface->Categories) { - serializeMembers(Record, Category->Ivars); - serializeMembers(Record, Category->Methods); - serializeMembers(Record, Category->Properties); +void SymbolGraphSerializer::visitObjCCategoryModuleRecord( + const ObjCCategoryModuleRecord &Record) { + Object Obj; + serializeObject(Obj, "identifier", + serializeIdentifier(Record, API.getLanguage())); + serializeObject( + Obj, "kind", + serializeSymbolKind(APIRecord::RK_ObjCCategoryModule, API.getLanguage())); + Obj["accessLevel"] = "public"; + Symbols.emplace_back(std::move(Obj)); - // Surface the protocols of the category to the interface. - for (const auto &Protocol : Category->Protocols) - serializeRelationship(RelationshipKind::ConformsTo, Record, Protocol); - } - } + // If the category is extended from an external module, it is then member of + // that module. + for (const auto &Category : Record.Categories) + serializeRelationship(RelationshipKind::MemberOf, *Category, Record); +} + +void SymbolGraphSerializer::visitObjCCategoryRecord( + const ObjCCategoryRecord &Record) { + auto ObjCCategory = serializeAPIRecord(Record); + + if (!ObjCCategory) + return; + + Symbols.emplace_back(std::move(*ObjCCategory)); + serializeMembers(Record, Record.Ivars); + serializeMembers(Record, Record.Methods); + serializeMembers(Record, Record.Properties); + + // Surface the protocols of the category to the interface. + for (const auto &Protocol : Record.Protocols) + serializeRelationship(RelationshipKind::ConformsTo, Record, Protocol); } void SymbolGraphSerializer::visitMacroDefinitionRecord( @@ -767,6 +788,12 @@ case APIRecord::RK_ObjCProtocol: visitObjCContainerRecord(*cast(Record)); break; + case APIRecord::RK_ObjCCategory: + visitObjCCategoryRecord(*cast(Record)); + break; + case APIRecord::RK_ObjCCategoryModule: + visitObjCCategoryModuleRecord(*cast(Record)); + break; case APIRecord::RK_MacroDefinition: visitMacroDefinitionRecord(*cast(Record)); break; @@ -835,9 +862,6 @@ if (!Record) return {}; - if (isa(Record)) - return {}; - Object Root; APIIgnoresList EmptyIgnores; SymbolGraphSerializer Serializer(API, EmptyIgnores, diff --git a/clang/test/ExtractAPI/objc_category.m b/clang/test/ExtractAPI/objc_category.m --- a/clang/test/ExtractAPI/objc_category.m +++ b/clang/test/ExtractAPI/objc_category.m @@ -54,24 +54,24 @@ { "kind": "memberOf", "source": "c:objc(cs)Interface(im)InstanceMethod", - "target": "c:objc(cs)Interface", - "targetFallback": "Interface" + "target": "c:objc(cy)Interface@Category", + "targetFallback": "Category" }, { "kind": "memberOf", "source": "c:objc(cs)Interface(cm)ClassMethod", - "target": "c:objc(cs)Interface", - "targetFallback": "Interface" + "target": "c:objc(cy)Interface@Category", + "targetFallback": "Category" }, { "kind": "memberOf", "source": "c:objc(cs)Interface(py)Property", - "target": "c:objc(cs)Interface", - "targetFallback": "Interface" + "target": "c:objc(cy)Interface@Category", + "targetFallback": "Category" }, { "kind": "conformsTo", - "source": "c:objc(cs)Interface", + "source": "c:objc(cy)Interface@Category", "target": "c:objc(pl)Protocol", "targetFallback": "Protocol" } @@ -127,6 +127,69 @@ "Interface" ] }, + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "@interface" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "typeIdentifier", + "preciseIdentifier": "c:objc(cs)Interface", + "spelling": "Interface" + }, + { + "kind": "text", + "spelling": " (" + }, + { + "kind": "identifier", + "spelling": "Category" + }, + { + "kind": "text", + "spelling": ")" + } + ], + "identifier": { + "interfaceLanguage": "objective-c", + "precise": "c:objc(cy)Interface@Category" + }, + "kind": { + "displayName": "Class Extension", + "identifier": "objective-c.class.extension" + }, + "location": { + "position": { + "character": 12, + "line": 6 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "Category" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "Category" + } + ], + "title": "Interface (Category)" + }, + "pathComponents": [ + "Category" + ] + }, { "accessLevel": "public", "declarationFragments": [ @@ -196,7 +259,7 @@ "title": "InstanceMethod" }, "pathComponents": [ - "Interface", + "Category", "InstanceMethod" ] }, @@ -269,7 +332,7 @@ "title": "ClassMethod" }, "pathComponents": [ - "Interface", + "Category", "ClassMethod" ] }, @@ -329,7 +392,7 @@ "title": "Property" }, "pathComponents": [ - "Interface", + "Category", "Property" ] } diff --git a/clang/test/ExtractAPI/objc_category.m b/clang/test/ExtractAPI/objc_module_category.m copy from clang/test/ExtractAPI/objc_category.m copy to clang/test/ExtractAPI/objc_module_category.m --- a/clang/test/ExtractAPI/objc_category.m +++ b/clang/test/ExtractAPI/objc_module_category.m @@ -14,15 +14,15 @@ // CHECK-NOT: warning: //--- input.h -@protocol Protocol; - -@interface Interface +#import +/// Doc comment 1 +@interface NSString (Category1) +-(void)method1; @end -@interface Interface (Category) -@property int Property; -- (void)InstanceMethod; -+ (void)ClassMethod; +/// Doc comment 2 +@interface NSString (Category2) +-(void)method2; @end //--- reference.output.json.in @@ -53,27 +53,27 @@ "relationships": [ { "kind": "memberOf", - "source": "c:objc(cs)Interface(im)InstanceMethod", - "target": "c:objc(cs)Interface", - "targetFallback": "Interface" + "source": "c:objc(cs)NSString(im)method1", + "target": "c:objc(cy)NSString@Category1", + "targetFallback": "Category1" }, { "kind": "memberOf", - "source": "c:objc(cs)Interface(cm)ClassMethod", - "target": "c:objc(cs)Interface", - "targetFallback": "Interface" + "source": "c:objc(cs)NSString(im)method2", + "target": "c:objc(cy)NSString@Category2", + "targetFallback": "Category2" }, { "kind": "memberOf", - "source": "c:objc(cs)Interface(py)Property", - "target": "c:objc(cs)Interface", - "targetFallback": "Interface" + "source": "c:objc(cy)NSString@Category1", + "target": "c:objc(cs)NSString", + "targetFallback": "NSString" }, { - "kind": "conformsTo", - "source": "c:objc(cs)Interface", - "target": "c:objc(pl)Protocol", - "targetFallback": "Protocol" + "kind": "memberOf", + "source": "c:objc(cy)NSString@Category2", + "target": "c:objc(cs)NSString", + "targetFallback": "NSString" } ], "symbols": [ @@ -88,18 +88,48 @@ "kind": "text", "spelling": " " }, + { + "kind": "typeIdentifier", + "preciseIdentifier": "c:objc(cs)NSString", + "spelling": "NSString" + }, + { + "kind": "text", + "spelling": " (" + }, { "kind": "identifier", - "spelling": "Interface" + "spelling": "Category1" + }, + { + "kind": "text", + "spelling": ")" } ], + "docComment": { + "lines": [ + { + "range": { + "end": { + "character": 18, + "line": 2 + }, + "start": { + "character": 5, + "line": 2 + } + }, + "text": "Doc comment 1" + } + ] + }, "identifier": { "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Interface" + "precise": "c:objc(cy)NSString@Category1" }, "kind": { - "displayName": "Class", - "identifier": "objective-c.class" + "displayName": "Class Extension", + "identifier": "objective-c.class.extension" }, "location": { "position": { @@ -112,19 +142,19 @@ "navigator": [ { "kind": "identifier", - "spelling": "Interface" + "spelling": "Category1" } ], "subHeading": [ { "kind": "identifier", - "spelling": "Interface" + "spelling": "Category1" } ], - "title": "Interface" + "title": "NSString (Category1)" }, "pathComponents": [ - "Interface" + "Category1" ] }, { @@ -145,7 +175,7 @@ }, { "kind": "identifier", - "spelling": "InstanceMethod" + "spelling": "method1" }, { "kind": "text", @@ -163,7 +193,7 @@ }, "identifier": { "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Interface(im)InstanceMethod" + "precise": "c:objc(cs)NSString(im)method1" }, "kind": { "displayName": "Instance Method", @@ -172,7 +202,7 @@ "location": { "position": { "character": 1, - "line": 8 + "line": 4 }, "uri": "file://INPUT_DIR/input.h" }, @@ -180,7 +210,7 @@ "navigator": [ { "kind": "identifier", - "spelling": "InstanceMethod" + "spelling": "method1" } ], "subHeading": [ @@ -190,62 +220,74 @@ }, { "kind": "identifier", - "spelling": "InstanceMethod" + "spelling": "method1" } ], - "title": "InstanceMethod" + "title": "method1" }, "pathComponents": [ - "Interface", - "InstanceMethod" + "Category1", + "method1" ] }, { "accessLevel": "public", "declarationFragments": [ + { + "kind": "keyword", + "spelling": "@interface" + }, { "kind": "text", - "spelling": "+ (" + "spelling": " " }, { "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" + "preciseIdentifier": "c:objc(cs)NSString", + "spelling": "NSString" }, { "kind": "text", - "spelling": ") " + "spelling": " (" }, { "kind": "identifier", - "spelling": "ClassMethod" + "spelling": "Category2" }, { "kind": "text", - "spelling": ";" + "spelling": ")" } ], - "functionSignature": { - "returns": [ + "docComment": { + "lines": [ { - "kind": "typeIdentifier", - "preciseIdentifier": "c:v", - "spelling": "void" + "range": { + "end": { + "character": 18, + "line": 7 + }, + "start": { + "character": 5, + "line": 7 + } + }, + "text": "Doc comment 2" } ] }, "identifier": { "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Interface(cm)ClassMethod" + "precise": "c:objc(cy)NSString@Category2" }, "kind": { - "displayName": "Type Method", - "identifier": "objective-c.type.method" + "displayName": "Class Extension", + "identifier": "objective-c.class.extension" }, "location": { "position": { - "character": 1, - "line": 9 + "character": 12, + "line": 8 }, "uri": "file://INPUT_DIR/input.h" }, @@ -253,63 +295,67 @@ "navigator": [ { "kind": "identifier", - "spelling": "ClassMethod" + "spelling": "Category2" } ], "subHeading": [ - { - "kind": "text", - "spelling": "+ " - }, { "kind": "identifier", - "spelling": "ClassMethod" + "spelling": "Category2" } ], - "title": "ClassMethod" + "title": "NSString (Category2)" }, "pathComponents": [ - "Interface", - "ClassMethod" + "Category2" ] }, { "accessLevel": "public", "declarationFragments": [ - { - "kind": "keyword", - "spelling": "@property" - }, { "kind": "text", - "spelling": " " + "spelling": "- (" }, { "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" + "preciseIdentifier": "c:v", + "spelling": "void" }, { "kind": "text", - "spelling": " " + "spelling": ") " }, { "kind": "identifier", - "spelling": "Property" + "spelling": "method2" + }, + { + "kind": "text", + "spelling": ";" } ], + "functionSignature": { + "returns": [ + { + "kind": "typeIdentifier", + "preciseIdentifier": "c:v", + "spelling": "void" + } + ] + }, "identifier": { "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Interface(py)Property" + "precise": "c:objc(cs)NSString(im)method2" }, "kind": { - "displayName": "Instance Property", - "identifier": "objective-c.property" + "displayName": "Instance Method", + "identifier": "objective-c.method" }, "location": { "position": { - "character": 15, - "line": 7 + "character": 1, + "line": 9 }, "uri": "file://INPUT_DIR/input.h" }, @@ -317,21 +363,36 @@ "navigator": [ { "kind": "identifier", - "spelling": "Property" + "spelling": "method2" } ], "subHeading": [ + { + "kind": "text", + "spelling": "- " + }, { "kind": "identifier", - "spelling": "Property" + "spelling": "method2" } ], - "title": "Property" + "title": "method2" }, "pathComponents": [ - "Interface", - "Property" + "Category2", + "method2" ] + }, + { + "accessLevel": "public", + "identifier": { + "interfaceLanguage": "objective-c", + "precise": "c:objc(cs)NSString" + }, + "kind": { + "displayName": "Module Extension", + "identifier": "objective-c.module.extension" + } } ] } diff --git a/clang/test/ExtractAPI/objc_property.m b/clang/test/ExtractAPI/objc_property.m --- a/clang/test/ExtractAPI/objc_property.m +++ b/clang/test/ExtractAPI/objc_property.m @@ -66,31 +66,31 @@ }, { "kind": "memberOf", - "source": "c:objc(cs)Interface(cpy)myCategoryTypeProp", - "target": "c:objc(cs)Interface", - "targetFallback": "Interface" + "source": "c:objc(pl)Protocol(cpy)myProtocolTypeProp", + "target": "c:objc(pl)Protocol", + "targetFallback": "Protocol" }, { "kind": "memberOf", - "source": "c:objc(cs)Interface(py)myCategoryInstanceProp", - "target": "c:objc(cs)Interface", - "targetFallback": "Interface" - }, - { - "kind": "conformsTo", - "source": "c:objc(cs)Interface", + "source": "c:objc(pl)Protocol(py)myProtocolInstanceProp", "target": "c:objc(pl)Protocol", "targetFallback": "Protocol" }, { "kind": "memberOf", - "source": "c:objc(pl)Protocol(cpy)myProtocolTypeProp", - "target": "c:objc(pl)Protocol", - "targetFallback": "Protocol" + "source": "c:objc(cs)Interface(cpy)myCategoryTypeProp", + "target": "c:objc(cy)Interface@Category", + "targetFallback": "Category" }, { "kind": "memberOf", - "source": "c:objc(pl)Protocol(py)myProtocolInstanceProp", + "source": "c:objc(cs)Interface(py)myCategoryInstanceProp", + "target": "c:objc(cy)Interface@Category", + "targetFallback": "Category" + }, + { + "kind": "conformsTo", + "source": "c:objc(cy)Interface@Category", "target": "c:objc(pl)Protocol", "targetFallback": "Protocol" } @@ -274,6 +274,56 @@ "myInterfaceInstanceProp" ] }, + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "@protocol" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "Protocol" + } + ], + "identifier": { + "interfaceLanguage": "objective-c", + "precise": "c:objc(pl)Protocol" + }, + "kind": { + "displayName": "Protocol", + "identifier": "objective-c.protocol" + }, + "location": { + "position": { + "character": 11, + "line": 1 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "Protocol" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "Protocol" + } + ], + "title": "Protocol" + }, + "pathComponents": [ + "Protocol" + ] + }, { "accessLevel": "public", "declarationFragments": [ @@ -304,12 +354,12 @@ }, { "kind": "identifier", - "spelling": "myCategoryTypeProp" + "spelling": "myProtocolTypeProp" } ], "identifier": { "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Interface(cpy)myCategoryTypeProp" + "precise": "c:objc(pl)Protocol(cpy)myProtocolTypeProp" }, "kind": { "displayName": "Type Property", @@ -318,7 +368,7 @@ "location": { "position": { "character": 22, - "line": 12 + "line": 2 }, "uri": "file://INPUT_DIR/input.h" }, @@ -326,20 +376,20 @@ "navigator": [ { "kind": "identifier", - "spelling": "myCategoryTypeProp" + "spelling": "myProtocolTypeProp" } ], "subHeading": [ { "kind": "identifier", - "spelling": "myCategoryTypeProp" + "spelling": "myProtocolTypeProp" } ], - "title": "myCategoryTypeProp" + "title": "myProtocolTypeProp" }, "pathComponents": [ - "Interface", - "myCategoryTypeProp" + "Protocol", + "myProtocolTypeProp" ] }, { @@ -364,12 +414,12 @@ }, { "kind": "identifier", - "spelling": "myCategoryInstanceProp" + "spelling": "myProtocolInstanceProp" } ], "identifier": { "interfaceLanguage": "objective-c", - "precise": "c:objc(cs)Interface(py)myCategoryInstanceProp" + "precise": "c:objc(pl)Protocol(py)myProtocolInstanceProp" }, "kind": { "displayName": "Instance Property", @@ -378,7 +428,7 @@ "location": { "position": { "character": 15, - "line": 13 + "line": 3 }, "uri": "file://INPUT_DIR/input.h" }, @@ -386,20 +436,20 @@ "navigator": [ { "kind": "identifier", - "spelling": "myCategoryInstanceProp" + "spelling": "myProtocolInstanceProp" } ], "subHeading": [ { "kind": "identifier", - "spelling": "myCategoryInstanceProp" + "spelling": "myProtocolInstanceProp" } ], - "title": "myCategoryInstanceProp" + "title": "myProtocolInstanceProp" }, "pathComponents": [ - "Interface", - "myCategoryInstanceProp" + "Protocol", + "myProtocolInstanceProp" ] }, { @@ -407,29 +457,42 @@ "declarationFragments": [ { "kind": "keyword", - "spelling": "@protocol" + "spelling": "@interface" }, { "kind": "text", "spelling": " " }, + { + "kind": "typeIdentifier", + "preciseIdentifier": "c:objc(cs)Interface", + "spelling": "Interface" + }, + { + "kind": "text", + "spelling": " (" + }, { "kind": "identifier", - "spelling": "Protocol" + "spelling": "Category" + }, + { + "kind": "text", + "spelling": ")" } ], "identifier": { "interfaceLanguage": "objective-c", - "precise": "c:objc(pl)Protocol" + "precise": "c:objc(cy)Interface@Category" }, "kind": { - "displayName": "Protocol", - "identifier": "objective-c.protocol" + "displayName": "Class Extension", + "identifier": "objective-c.class.extension" }, "location": { "position": { - "character": 11, - "line": 1 + "character": 12, + "line": 11 }, "uri": "file://INPUT_DIR/input.h" }, @@ -437,19 +500,19 @@ "navigator": [ { "kind": "identifier", - "spelling": "Protocol" + "spelling": "Category" } ], "subHeading": [ { "kind": "identifier", - "spelling": "Protocol" + "spelling": "Category" } ], - "title": "Protocol" + "title": "Interface (Category)" }, "pathComponents": [ - "Protocol" + "Category" ] }, { @@ -482,12 +545,12 @@ }, { "kind": "identifier", - "spelling": "myProtocolTypeProp" + "spelling": "myCategoryTypeProp" } ], "identifier": { "interfaceLanguage": "objective-c", - "precise": "c:objc(pl)Protocol(cpy)myProtocolTypeProp" + "precise": "c:objc(cs)Interface(cpy)myCategoryTypeProp" }, "kind": { "displayName": "Type Property", @@ -496,7 +559,7 @@ "location": { "position": { "character": 22, - "line": 2 + "line": 12 }, "uri": "file://INPUT_DIR/input.h" }, @@ -504,20 +567,20 @@ "navigator": [ { "kind": "identifier", - "spelling": "myProtocolTypeProp" + "spelling": "myCategoryTypeProp" } ], "subHeading": [ { "kind": "identifier", - "spelling": "myProtocolTypeProp" + "spelling": "myCategoryTypeProp" } ], - "title": "myProtocolTypeProp" + "title": "myCategoryTypeProp" }, "pathComponents": [ - "Protocol", - "myProtocolTypeProp" + "Category", + "myCategoryTypeProp" ] }, { @@ -542,12 +605,12 @@ }, { "kind": "identifier", - "spelling": "myProtocolInstanceProp" + "spelling": "myCategoryInstanceProp" } ], "identifier": { "interfaceLanguage": "objective-c", - "precise": "c:objc(pl)Protocol(py)myProtocolInstanceProp" + "precise": "c:objc(cs)Interface(py)myCategoryInstanceProp" }, "kind": { "displayName": "Instance Property", @@ -556,7 +619,7 @@ "location": { "position": { "character": 15, - "line": 3 + "line": 13 }, "uri": "file://INPUT_DIR/input.h" }, @@ -564,20 +627,20 @@ "navigator": [ { "kind": "identifier", - "spelling": "myProtocolInstanceProp" + "spelling": "myCategoryInstanceProp" } ], "subHeading": [ { "kind": "identifier", - "spelling": "myProtocolInstanceProp" + "spelling": "myCategoryInstanceProp" } ], - "title": "myProtocolInstanceProp" + "title": "myCategoryInstanceProp" }, "pathComponents": [ - "Protocol", - "myProtocolInstanceProp" + "Category", + "myCategoryInstanceProp" ] } ]