From 7443a504bf6c22b83727c1e43c82c4165b2d5db5 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Mon, 11 Apr 2022 19:53:33 +0100 Subject: [PATCH] [clang][extract-api] Add support for true anonymous enums Anonymous enums without a typedef should have a "(anonymous)" identifier. Differential Revision: https://reviews.llvm.org/D123533 --- clang/include/clang/ExtractAPI/API.h | 71 ++++--- clang/lib/ExtractAPI/API.cpp | 36 ++-- clang/lib/ExtractAPI/ExtractAPIConsumer.cpp | 9 +- clang/test/ExtractAPI/enum.c | 194 ++++++++++++++++++++ 4 files changed, 253 insertions(+), 57 deletions(-) diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h index 6a9429704d45..53db46ca44c1 100644 --- a/clang/include/clang/ExtractAPI/API.h +++ b/clang/include/clang/ExtractAPI/API.h @@ -50,13 +50,13 @@ namespace extractapi { /// \endcode using DocComment = std::vector; -// Classes deriving from APIRecord need to have Name be the first constructor +// Classes deriving from APIRecord need to have USR be the first constructor // argument. This is so that they are compatible with `addTopLevelRecord` // defined in API.cpp /// The base representation of an API record. Holds common symbol information. struct APIRecord { - StringRef Name; StringRef USR; + StringRef Name; PresumedLoc Location; AvailabilityInfo Availability; LinkageInfo Linkage; @@ -101,11 +101,11 @@ public: APIRecord() = delete; - APIRecord(RecordKind Kind, StringRef Name, StringRef USR, + APIRecord(RecordKind Kind, StringRef USR, StringRef Name, PresumedLoc Location, const AvailabilityInfo &Availability, LinkageInfo Linkage, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading) - : Name(Name), USR(USR), Location(Location), Availability(Availability), + : USR(USR), Name(Name), Location(Location), Availability(Availability), Linkage(Linkage), Comment(Comment), Declaration(Declaration), SubHeading(SubHeading), Kind(Kind) {} @@ -117,13 +117,13 @@ public: struct GlobalFunctionRecord : APIRecord { FunctionSignature Signature; - GlobalFunctionRecord(StringRef Name, StringRef USR, PresumedLoc Loc, + GlobalFunctionRecord(StringRef USR, StringRef Name, PresumedLoc Loc, const AvailabilityInfo &Availability, LinkageInfo Linkage, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, FunctionSignature Signature) - : APIRecord(RK_GlobalFunction, Name, USR, Loc, Availability, Linkage, + : APIRecord(RK_GlobalFunction, USR, Name, Loc, Availability, Linkage, Comment, Declaration, SubHeading), Signature(Signature) {} @@ -137,12 +137,12 @@ private: /// This holds information associated with global functions. struct GlobalVariableRecord : APIRecord { - GlobalVariableRecord(StringRef Name, StringRef USR, PresumedLoc Loc, + GlobalVariableRecord(StringRef USR, StringRef Name, PresumedLoc Loc, const AvailabilityInfo &Availability, LinkageInfo Linkage, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading) - : APIRecord(RK_GlobalVariable, Name, USR, Loc, Availability, Linkage, + : APIRecord(RK_GlobalVariable, USR, Name, Loc, Availability, Linkage, Comment, Declaration, SubHeading) {} static bool classof(const APIRecord *Record) { @@ -155,12 +155,12 @@ private: /// This holds information associated with enum constants. struct EnumConstantRecord : APIRecord { - EnumConstantRecord(StringRef Name, StringRef USR, PresumedLoc Loc, + EnumConstantRecord(StringRef USR, StringRef Name, PresumedLoc Loc, const AvailabilityInfo &Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading) - : APIRecord(RK_EnumConstant, Name, USR, Loc, Availability, + : APIRecord(RK_EnumConstant, USR, Name, Loc, Availability, LinkageInfo::none(), Comment, Declaration, SubHeading) {} static bool classof(const APIRecord *Record) { @@ -175,10 +175,10 @@ private: struct EnumRecord : APIRecord { SmallVector> Constants; - EnumRecord(StringRef Name, StringRef USR, PresumedLoc Loc, + EnumRecord(StringRef USR, StringRef Name, PresumedLoc Loc, const AvailabilityInfo &Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading) - : APIRecord(RK_Enum, Name, USR, Loc, Availability, LinkageInfo::none(), + : APIRecord(RK_Enum, USR, Name, Loc, Availability, LinkageInfo::none(), Comment, Declaration, SubHeading) {} static bool classof(const APIRecord *Record) { @@ -191,11 +191,11 @@ private: /// This holds information associated with struct fields. struct StructFieldRecord : APIRecord { - StructFieldRecord(StringRef Name, StringRef USR, PresumedLoc Loc, + StructFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc, const AvailabilityInfo &Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading) - : APIRecord(RK_StructField, Name, USR, Loc, Availability, + : APIRecord(RK_StructField, USR, Name, Loc, Availability, LinkageInfo::none(), Comment, Declaration, SubHeading) {} static bool classof(const APIRecord *Record) { @@ -210,11 +210,11 @@ private: struct StructRecord : APIRecord { SmallVector> Fields; - StructRecord(StringRef Name, StringRef USR, PresumedLoc Loc, + StructRecord(StringRef USR, StringRef Name, PresumedLoc Loc, const AvailabilityInfo &Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading) - : APIRecord(RK_Struct, Name, USR, Loc, Availability, LinkageInfo::none(), + : APIRecord(RK_Struct, USR, Name, Loc, Availability, LinkageInfo::none(), Comment, Declaration, SubHeading) {} static bool classof(const APIRecord *Record) { @@ -240,14 +240,14 @@ struct ObjCPropertyRecord : APIRecord { StringRef SetterName; bool IsOptional; - ObjCPropertyRecord(StringRef Name, StringRef USR, PresumedLoc Loc, + ObjCPropertyRecord(StringRef USR, StringRef Name, PresumedLoc Loc, const AvailabilityInfo &Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, AttributeKind Attributes, StringRef GetterName, StringRef SetterName, bool IsOptional) - : APIRecord(RK_ObjCProperty, Name, USR, Loc, Availability, + : APIRecord(RK_ObjCProperty, USR, Name, Loc, Availability, LinkageInfo::none(), Comment, Declaration, SubHeading), Attributes(Attributes), GetterName(GetterName), SetterName(SetterName), IsOptional(IsOptional) {} @@ -269,13 +269,13 @@ struct ObjCInstanceVariableRecord : APIRecord { using AccessControl = ObjCIvarDecl::AccessControl; AccessControl Access; - ObjCInstanceVariableRecord(StringRef Name, StringRef USR, PresumedLoc Loc, + ObjCInstanceVariableRecord(StringRef USR, StringRef Name, PresumedLoc Loc, const AvailabilityInfo &Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, AccessControl Access) - : APIRecord(RK_ObjCIvar, Name, USR, Loc, Availability, + : APIRecord(RK_ObjCIvar, USR, Name, Loc, Availability, LinkageInfo::none(), Comment, Declaration, SubHeading), Access(Access) {} @@ -292,12 +292,12 @@ struct ObjCMethodRecord : APIRecord { FunctionSignature Signature; bool IsInstanceMethod; - ObjCMethodRecord(StringRef Name, StringRef USR, PresumedLoc Loc, + ObjCMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc, const AvailabilityInfo &Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, FunctionSignature Signature, bool IsInstanceMethod) - : APIRecord(RK_ObjCMethod, Name, USR, Loc, Availability, + : APIRecord(RK_ObjCMethod, USR, Name, Loc, Availability, LinkageInfo::none(), Comment, Declaration, SubHeading), Signature(Signature), IsInstanceMethod(IsInstanceMethod) {} @@ -340,12 +340,12 @@ struct ObjCContainerRecord : APIRecord { ObjCContainerRecord() = delete; - ObjCContainerRecord(RecordKind Kind, StringRef Name, StringRef USR, + ObjCContainerRecord(RecordKind Kind, StringRef USR, StringRef Name, PresumedLoc Loc, const AvailabilityInfo &Availability, LinkageInfo Linkage, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading) - : APIRecord(Kind, Name, USR, Loc, Availability, Linkage, Comment, + : APIRecord(Kind, USR, Name, Loc, Availability, Linkage, Comment, Declaration, SubHeading) {} virtual ~ObjCContainerRecord() = 0; @@ -355,12 +355,12 @@ struct ObjCContainerRecord : APIRecord { struct ObjCCategoryRecord : ObjCContainerRecord { SymbolReference Interface; - ObjCCategoryRecord(StringRef Name, StringRef USR, PresumedLoc Loc, + ObjCCategoryRecord(StringRef USR, StringRef Name, PresumedLoc Loc, const AvailabilityInfo &Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, SymbolReference Interface) - : ObjCContainerRecord(RK_ObjCCategory, Name, USR, Loc, Availability, + : ObjCContainerRecord(RK_ObjCCategory, USR, Name, Loc, Availability, LinkageInfo::none(), Comment, Declaration, SubHeading), Interface(Interface) {} @@ -379,13 +379,13 @@ struct ObjCInterfaceRecord : ObjCContainerRecord { // ObjCCategoryRecord%s are stored in and owned by APISet. SmallVector Categories; - ObjCInterfaceRecord(StringRef Name, StringRef USR, PresumedLoc Loc, + ObjCInterfaceRecord(StringRef USR, StringRef Name, PresumedLoc Loc, const AvailabilityInfo &Availability, LinkageInfo Linkage, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, SymbolReference SuperClass) - : ObjCContainerRecord(RK_ObjCInterface, Name, USR, Loc, Availability, + : ObjCContainerRecord(RK_ObjCInterface, USR, Name, Loc, Availability, Linkage, Comment, Declaration, SubHeading), SuperClass(SuperClass) {} @@ -399,12 +399,12 @@ private: /// This holds information associated with Objective-C protocols. struct ObjCProtocolRecord : ObjCContainerRecord { - ObjCProtocolRecord(StringRef Name, StringRef USR, PresumedLoc Loc, + ObjCProtocolRecord(StringRef USR, StringRef Name, PresumedLoc Loc, const AvailabilityInfo &Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading) - : ObjCContainerRecord(RK_ObjCProtocol, Name, USR, Loc, Availability, + : ObjCContainerRecord(RK_ObjCProtocol, USR, Name, Loc, Availability, LinkageInfo::none(), Comment, Declaration, SubHeading) {} @@ -418,10 +418,10 @@ private: /// This holds information associated with macro definitions. struct MacroDefinitionRecord : APIRecord { - MacroDefinitionRecord(StringRef Name, StringRef USR, PresumedLoc Loc, + MacroDefinitionRecord(StringRef USR, StringRef Name, PresumedLoc Loc, DeclarationFragments Declaration, DeclarationFragments SubHeading) - : APIRecord(RK_MacroDefinition, Name, USR, Loc, AvailabilityInfo(), + : APIRecord(RK_MacroDefinition, USR, Name, Loc, AvailabilityInfo(), LinkageInfo(), {}, Declaration, SubHeading) {} static bool classof(const APIRecord *Record) { @@ -440,11 +440,11 @@ private: struct TypedefRecord : APIRecord { SymbolReference UnderlyingType; - TypedefRecord(StringRef Name, StringRef USR, PresumedLoc Loc, + TypedefRecord(StringRef USR, StringRef Name, PresumedLoc Loc, const AvailabilityInfo &Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, SymbolReference UnderlyingType) - : APIRecord(RK_Typedef, Name, USR, Loc, Availability, LinkageInfo(), + : APIRecord(RK_Typedef, USR, Name, Loc, Availability, LinkageInfo(), Comment, Declaration, SubHeading), UnderlyingType(UnderlyingType) {} @@ -647,8 +647,7 @@ public: DeclarationFragments SubHeading, SymbolReference UnderlyingType); - /// A mapping type to store a set of APIRecord%s with the declaration name as - /// the key. + /// A mapping type to store a set of APIRecord%s with the USR as the key. template ::value>> diff --git a/clang/lib/ExtractAPI/API.cpp b/clang/lib/ExtractAPI/API.cpp index 10d723d452ca..073e36f320d3 100644 --- a/clang/lib/ExtractAPI/API.cpp +++ b/clang/lib/ExtractAPI/API.cpp @@ -28,13 +28,13 @@ namespace { template RecordTy *addTopLevelRecord(APISet::RecordMap &RecordMap, - StringRef Name, CtorArgsTy &&...CtorArgs) { - auto Result = RecordMap.insert({Name, nullptr}); + StringRef USR, CtorArgsTy &&...CtorArgs) { + auto Result = RecordMap.insert({USR, nullptr}); // Create the record if it does not already exist if (Result.second) Result.first->second = - std::make_unique(Name, std::forward(CtorArgs)...); + std::make_unique(USR, std::forward(CtorArgs)...); return Result.first->second.get(); } @@ -46,7 +46,7 @@ APISet::addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc, const AvailabilityInfo &Availability, LinkageInfo Linkage, const DocComment &Comment, DeclarationFragments Fragments, DeclarationFragments SubHeading) { - return addTopLevelRecord(GlobalVariables, Name, USR, Loc, Availability, + return addTopLevelRecord(GlobalVariables, USR, Name, Loc, Availability, Linkage, Comment, Fragments, SubHeading); } @@ -55,7 +55,7 @@ GlobalFunctionRecord *APISet::addGlobalFunction( const AvailabilityInfo &Availability, LinkageInfo Linkage, const DocComment &Comment, DeclarationFragments Fragments, DeclarationFragments SubHeading, FunctionSignature Signature) { - return addTopLevelRecord(GlobalFunctions, Name, USR, Loc, Availability, + return addTopLevelRecord(GlobalFunctions, USR, Name, Loc, Availability, Linkage, Comment, Fragments, SubHeading, Signature); } @@ -64,7 +64,7 @@ EnumConstantRecord *APISet::addEnumConstant( const AvailabilityInfo &Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading) { auto Record = std::make_unique( - Name, USR, Loc, Availability, Comment, Declaration, SubHeading); + USR, Name, Loc, Availability, Comment, Declaration, SubHeading); return Enum->Constants.emplace_back(std::move(Record)).get(); } @@ -73,7 +73,7 @@ EnumRecord *APISet::addEnum(StringRef Name, StringRef USR, PresumedLoc Loc, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading) { - return addTopLevelRecord(Enums, Name, USR, Loc, Availability, Comment, + return addTopLevelRecord(Enums, USR, Name, Loc, Availability, Comment, Declaration, SubHeading); } @@ -84,7 +84,7 @@ StructFieldRecord *APISet::addStructField(StructRecord *Struct, StringRef Name, DeclarationFragments Declaration, DeclarationFragments SubHeading) { auto Record = std::make_unique( - Name, USR, Loc, Availability, Comment, Declaration, SubHeading); + USR, Name, Loc, Availability, Comment, Declaration, SubHeading); return Struct->Fields.emplace_back(std::move(Record)).get(); } @@ -93,7 +93,7 @@ StructRecord *APISet::addStruct(StringRef Name, StringRef USR, PresumedLoc Loc, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading) { - return addTopLevelRecord(Structs, Name, USR, Loc, Availability, Comment, + return addTopLevelRecord(Structs, USR, Name, Loc, Availability, Comment, Declaration, SubHeading); } @@ -103,12 +103,12 @@ ObjCCategoryRecord *APISet::addObjCCategory( DeclarationFragments Declaration, DeclarationFragments SubHeading, SymbolReference Interface) { // Create the category record. - auto *Record = addTopLevelRecord(ObjCCategories, Name, USR, Loc, Availability, + auto *Record = addTopLevelRecord(ObjCCategories, USR, Name, Loc, Availability, Comment, Declaration, SubHeading, Interface); // If this category is extending a known interface, associate it with the // ObjCInterfaceRecord. - auto It = ObjCInterfaces.find(Interface.Name); + auto It = ObjCInterfaces.find(Interface.USR); if (It != ObjCInterfaces.end()) It->second->Categories.push_back(Record); @@ -120,7 +120,7 @@ ObjCInterfaceRecord *APISet::addObjCInterface( const AvailabilityInfo &Availability, LinkageInfo Linkage, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, SymbolReference SuperClass) { - return addTopLevelRecord(ObjCInterfaces, Name, USR, Loc, Availability, + return addTopLevelRecord(ObjCInterfaces, USR, Name, Loc, Availability, Linkage, Comment, Declaration, SubHeading, SuperClass); } @@ -132,7 +132,7 @@ ObjCMethodRecord *APISet::addObjCMethod( DeclarationFragments SubHeading, FunctionSignature Signature, bool IsInstanceMethod) { auto Record = std::make_unique( - Name, USR, Loc, Availability, Comment, Declaration, SubHeading, Signature, + USR, Name, Loc, Availability, Comment, Declaration, SubHeading, Signature, IsInstanceMethod); return Container->Methods.emplace_back(std::move(Record)).get(); } @@ -145,7 +145,7 @@ ObjCPropertyRecord *APISet::addObjCProperty( ObjCPropertyRecord::AttributeKind Attributes, StringRef GetterName, StringRef SetterName, bool IsOptional) { auto Record = std::make_unique( - Name, USR, Loc, Availability, Comment, Declaration, SubHeading, + USR, Name, Loc, Availability, Comment, Declaration, SubHeading, Attributes, GetterName, SetterName, IsOptional); return Container->Properties.emplace_back(std::move(Record)).get(); } @@ -157,7 +157,7 @@ ObjCInstanceVariableRecord *APISet::addObjCInstanceVariable( DeclarationFragments SubHeading, ObjCInstanceVariableRecord::AccessControl Access) { auto Record = std::make_unique( - Name, USR, Loc, Availability, Comment, Declaration, SubHeading, Access); + USR, Name, Loc, Availability, Comment, Declaration, SubHeading, Access); return Container->Ivars.emplace_back(std::move(Record)).get(); } @@ -165,7 +165,7 @@ ObjCProtocolRecord *APISet::addObjCProtocol( StringRef Name, StringRef USR, PresumedLoc Loc, const AvailabilityInfo &Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading) { - return addTopLevelRecord(ObjCProtocols, Name, USR, Loc, Availability, Comment, + return addTopLevelRecord(ObjCProtocols, USR, Name, Loc, Availability, Comment, Declaration, SubHeading); } @@ -173,7 +173,7 @@ MacroDefinitionRecord * APISet::addMacroDefinition(StringRef Name, StringRef USR, PresumedLoc Loc, DeclarationFragments Declaration, DeclarationFragments SubHeading) { - return addTopLevelRecord(Macros, Name, USR, Loc, Declaration, SubHeading); + return addTopLevelRecord(Macros, USR, Name, Loc, Declaration, SubHeading); } TypedefRecord *APISet::addTypedef(StringRef Name, StringRef USR, @@ -183,7 +183,7 @@ TypedefRecord *APISet::addTypedef(StringRef Name, StringRef USR, DeclarationFragments Declaration, DeclarationFragments SubHeading, SymbolReference UnderlyingType) { - return addTopLevelRecord(Typedefs, Name, USR, Loc, Availability, Comment, + return addTopLevelRecord(Typedefs, USR, Name, Loc, Availability, Comment, Declaration, SubHeading, UnderlyingType); } diff --git a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp index e3700a0d390a..0217c656cbb0 100644 --- a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp +++ b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp @@ -215,9 +215,11 @@ public: return true; // Collect symbol information. - StringRef Name = Decl->getName(); + std::string NameString = Decl->getQualifiedNameAsString(); + StringRef Name(NameString); if (Name.empty()) Name = getTypedefName(Decl); + StringRef USR = API.recordUSR(Decl); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); @@ -233,8 +235,9 @@ public: DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); - EnumRecord *EnumRecord = API.addEnum(Name, USR, Loc, Availability, Comment, - Declaration, SubHeading); + EnumRecord *EnumRecord = + API.addEnum(API.copyString(Name), USR, Loc, Availability, Comment, + Declaration, SubHeading); // Now collect information about the enumerators in this enum. recordEnumConstants(EnumRecord, Decl->enumerators()); diff --git a/clang/test/ExtractAPI/enum.c b/clang/test/ExtractAPI/enum.c index 49e39f7ba410..a14666a03747 100644 --- a/clang/test/ExtractAPI/enum.c +++ b/clang/test/ExtractAPI/enum.c @@ -30,6 +30,14 @@ enum Direction : unsigned char { West }; +enum { + Constant = 1 +}; + +enum { + OtherConstant = 2 +}; + //--- reference.output.json.in { "metadata": { @@ -100,6 +108,16 @@ enum Direction : unsigned char { "kind": "memberOf", "source": "c:@E@Direction@West", "target": "c:@E@Direction" + }, + { + "kind": "memberOf", + "source": "c:@Ea@Constant@Constant", + "target": "c:@Ea@Constant" + }, + { + "kind": "memberOf", + "source": "c:@Ea@OtherConstant@OtherConstant", + "target": "c:@Ea@OtherConstant" } ], "symbols": [ @@ -641,6 +659,182 @@ enum Direction : unsigned char { "Direction", "West" ] + }, + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "enum" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "preciseIdentifier": "c:i", + "spelling": "unsigned int" + } + ], + "identifier": { + "interfaceLanguage": "c", + "precise": "c:@Ea@Constant" + }, + "kind": { + "displayName": "Enumeration", + "identifier": "c.enum" + }, + "location": { + "position": { + "character": 1, + "line": 17 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "(anonymous)" + } + ], + "title": "(anonymous)" + }, + "pathComponents": [ + "(anonymous)" + ] + }, + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "Constant" + } + ], + "identifier": { + "interfaceLanguage": "c", + "precise": "c:@Ea@Constant@Constant" + }, + "kind": { + "displayName": "Enumeration Case", + "identifier": "c.enum.case" + }, + "location": { + "position": { + "character": 3, + "line": 18 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "Constant" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "Constant" + } + ], + "title": "Constant" + }, + "pathComponents": [ + "(anonymous)", + "Constant" + ] + }, + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "enum" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "preciseIdentifier": "c:i", + "spelling": "unsigned int" + } + ], + "identifier": { + "interfaceLanguage": "c", + "precise": "c:@Ea@OtherConstant" + }, + "kind": { + "displayName": "Enumeration", + "identifier": "c.enum" + }, + "location": { + "position": { + "character": 1, + "line": 21 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "(anonymous)" + } + ], + "title": "(anonymous)" + }, + "pathComponents": [ + "(anonymous)" + ] + }, + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "OtherConstant" + } + ], + "identifier": { + "interfaceLanguage": "c", + "precise": "c:@Ea@OtherConstant@OtherConstant" + }, + "kind": { + "displayName": "Enumeration Case", + "identifier": "c.enum.case" + }, + "location": { + "position": { + "character": 3, + "line": 22 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "OtherConstant" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "OtherConstant" + } + ], + "title": "OtherConstant" + }, + "pathComponents": [ + "(anonymous)", + "OtherConstant" + ] } ] }