zixuw created this revision.
Herald added a reviewer: dang.
Herald added a project: All.
zixuw requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Add support for enum records

- Add `EnumConstantRecord` and `EnumRecord` to store API information for enums
- Implement `VisitEnumDecl` in `ExtractAPIVisitor`
- Implement serializatin for enum records and `MemberOf` relationship
- Add test case for enum records
- Few other improvements


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D121873

Files:
  clang/include/clang/SymbolGraph/API.h
  clang/include/clang/SymbolGraph/DeclarationFragments.h
  clang/include/clang/SymbolGraph/Serialization.h
  clang/lib/SymbolGraph/API.cpp
  clang/lib/SymbolGraph/DeclarationFragments.cpp
  clang/lib/SymbolGraph/ExtractAPIConsumer.cpp
  clang/lib/SymbolGraph/Serialization.cpp
  clang/test/SymbolGraph/enum.c

Index: clang/test/SymbolGraph/enum.c
===================================================================
--- /dev/null
+++ clang/test/SymbolGraph/enum.c
@@ -0,0 +1,505 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: sed -e "s@INPUT_DIR@%/t@g" %t/reference.output.json.in >> \
+// RUN: %t/reference.output.json
+// RUN: %clang -extract-api -target arm64-apple-macosx \
+// RUN: %t/input.c -o %t/output.json | FileCheck -allow-empty %s
+
+// Generator version is not consistent across test runs, normalize it.
+// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
+// RUN: %t/output.json >> %t/output-normalized.json
+// RUN: diff %t/reference.output.json %t/output-normalized.json
+
+// CHECK-NOT: error:
+// CHECK-NOT: warning:
+
+//--- input.c
+/// Kinds of vehicles
+enum Vehicle {
+  Bicycle,
+  Car,
+  Train, ///< Move this to the top! -Sheldon
+  Ship,
+  Airplane,
+};
+
+enum Direction : unsigned char {
+  North = 0,
+  East,
+  South,
+  West
+};
+
+//--- reference.output.json.in
+{
+  "metadata": {
+    "formatVersion": {
+      "major": 0,
+      "minor": 5,
+      "patch": 3
+    },
+    "generator": "?"
+  },
+  "module": {
+    "name": "",
+    "platform": {
+      "architecture": "arm64",
+      "operatingSystem": {
+        "minimumVersion": {
+          "major": 11,
+          "minor": 0,
+          "patch": 0
+        },
+        "name": "macosx"
+      },
+      "vendor": "apple"
+    }
+  },
+  "relationhips": [
+    {
+      "kind": "memberOf",
+      "source": "c:@E@Vehicle@Bicycle",
+      "target": "c:@E@Vehicle"
+    },
+    {
+      "kind": "memberOf",
+      "source": "c:@E@Vehicle@Car",
+      "target": "c:@E@Vehicle"
+    },
+    {
+      "kind": "memberOf",
+      "source": "c:@E@Vehicle@Train",
+      "target": "c:@E@Vehicle"
+    },
+    {
+      "kind": "memberOf",
+      "source": "c:@E@Vehicle@Ship",
+      "target": "c:@E@Vehicle"
+    },
+    {
+      "kind": "memberOf",
+      "source": "c:@E@Vehicle@Airplane",
+      "target": "c:@E@Vehicle"
+    },
+    {
+      "kind": "memberOf",
+      "source": "c:@E@Direction@North",
+      "target": "c:@E@Direction"
+    },
+    {
+      "kind": "memberOf",
+      "source": "c:@E@Direction@East",
+      "target": "c:@E@Direction"
+    },
+    {
+      "kind": "memberOf",
+      "source": "c:@E@Direction@South",
+      "target": "c:@E@Direction"
+    },
+    {
+      "kind": "memberOf",
+      "source": "c:@E@Direction@West",
+      "target": "c:@E@Direction"
+    }
+  ],
+  "symbols": [
+    {
+      "declarationFragments": [
+        {
+          "kind": "keyword",
+          "spelling": "enum"
+        },
+        {
+          "kind": "text",
+          "spelling": " "
+        },
+        {
+          "kind": "identifier",
+          "spelling": "Vehicle"
+        },
+        {
+          "kind": "text",
+          "spelling": ": "
+        },
+        {
+          "kind": "typeIdentifier",
+          "preciseIdentifier": "c:i",
+          "spelling": "unsigned int"
+        }
+      ],
+      "docComment": {
+        "lines": [
+          {
+            "range": {
+              "end": {
+                "character": 22,
+                "line": 1
+              },
+              "start": {
+                "character": 5,
+                "line": 1
+              }
+            },
+            "text": "Kinds of vehicles"
+          }
+        ]
+      },
+      "identifier": {
+        "interfaceLanguage": "c",
+        "precise": "c:@E@Vehicle"
+      },
+      "kind": {
+        "displayName": "Enum",
+        "identifier": "c.enum"
+      },
+      "location": {
+        "character": 6,
+        "line": 2,
+        "uri": "file://INPUT_DIR/input.c"
+      },
+      "names": {
+        "subHeading": [
+          {
+            "kind": "identifier",
+            "spelling": "Vehicle"
+          }
+        ],
+        "title": "Vehicle"
+      }
+    },
+    {
+      "declarationFragments": [
+        {
+          "kind": "identifier",
+          "spelling": "Bicycle"
+        }
+      ],
+      "identifier": {
+        "interfaceLanguage": "c",
+        "precise": "c:@E@Vehicle@Bicycle"
+      },
+      "kind": {
+        "displayName": "Enum Case",
+        "identifier": "c.enum.case"
+      },
+      "location": {
+        "character": 3,
+        "line": 3,
+        "uri": "file://INPUT_DIR/input.c"
+      },
+      "names": {
+        "subHeading": [
+          {
+            "kind": "identifier",
+            "spelling": "Bicycle"
+          }
+        ],
+        "title": "Bicycle"
+      }
+    },
+    {
+      "declarationFragments": [
+        {
+          "kind": "identifier",
+          "spelling": "Car"
+        }
+      ],
+      "identifier": {
+        "interfaceLanguage": "c",
+        "precise": "c:@E@Vehicle@Car"
+      },
+      "kind": {
+        "displayName": "Enum Case",
+        "identifier": "c.enum.case"
+      },
+      "location": {
+        "character": 3,
+        "line": 4,
+        "uri": "file://INPUT_DIR/input.c"
+      },
+      "names": {
+        "subHeading": [
+          {
+            "kind": "identifier",
+            "spelling": "Car"
+          }
+        ],
+        "title": "Car"
+      }
+    },
+    {
+      "declarationFragments": [
+        {
+          "kind": "identifier",
+          "spelling": "Train"
+        }
+      ],
+      "docComment": {
+        "lines": [
+          {
+            "range": {
+              "end": {
+                "character": 45,
+                "line": 5
+              },
+              "start": {
+                "character": 15,
+                "line": 5
+              }
+            },
+            "text": "Move this to the top! -Sheldon"
+          }
+        ]
+      },
+      "identifier": {
+        "interfaceLanguage": "c",
+        "precise": "c:@E@Vehicle@Train"
+      },
+      "kind": {
+        "displayName": "Enum Case",
+        "identifier": "c.enum.case"
+      },
+      "location": {
+        "character": 3,
+        "line": 5,
+        "uri": "file://INPUT_DIR/input.c"
+      },
+      "names": {
+        "subHeading": [
+          {
+            "kind": "identifier",
+            "spelling": "Train"
+          }
+        ],
+        "title": "Train"
+      }
+    },
+    {
+      "declarationFragments": [
+        {
+          "kind": "identifier",
+          "spelling": "Ship"
+        }
+      ],
+      "identifier": {
+        "interfaceLanguage": "c",
+        "precise": "c:@E@Vehicle@Ship"
+      },
+      "kind": {
+        "displayName": "Enum Case",
+        "identifier": "c.enum.case"
+      },
+      "location": {
+        "character": 3,
+        "line": 6,
+        "uri": "file://INPUT_DIR/input.c"
+      },
+      "names": {
+        "subHeading": [
+          {
+            "kind": "identifier",
+            "spelling": "Ship"
+          }
+        ],
+        "title": "Ship"
+      }
+    },
+    {
+      "declarationFragments": [
+        {
+          "kind": "identifier",
+          "spelling": "Airplane"
+        }
+      ],
+      "identifier": {
+        "interfaceLanguage": "c",
+        "precise": "c:@E@Vehicle@Airplane"
+      },
+      "kind": {
+        "displayName": "Enum Case",
+        "identifier": "c.enum.case"
+      },
+      "location": {
+        "character": 3,
+        "line": 7,
+        "uri": "file://INPUT_DIR/input.c"
+      },
+      "names": {
+        "subHeading": [
+          {
+            "kind": "identifier",
+            "spelling": "Airplane"
+          }
+        ],
+        "title": "Airplane"
+      }
+    },
+    {
+      "declarationFragments": [
+        {
+          "kind": "keyword",
+          "spelling": "enum"
+        },
+        {
+          "kind": "text",
+          "spelling": " "
+        },
+        {
+          "kind": "identifier",
+          "spelling": "Direction"
+        },
+        {
+          "kind": "text",
+          "spelling": ": "
+        },
+        {
+          "kind": "typeIdentifier",
+          "preciseIdentifier": "c:c",
+          "spelling": "unsigned char"
+        }
+      ],
+      "identifier": {
+        "interfaceLanguage": "c",
+        "precise": "c:@E@Direction"
+      },
+      "kind": {
+        "displayName": "Enum",
+        "identifier": "c.enum"
+      },
+      "location": {
+        "character": 6,
+        "line": 10,
+        "uri": "file://INPUT_DIR/input.c"
+      },
+      "names": {
+        "subHeading": [
+          {
+            "kind": "identifier",
+            "spelling": "Direction"
+          }
+        ],
+        "title": "Direction"
+      }
+    },
+    {
+      "declarationFragments": [
+        {
+          "kind": "identifier",
+          "spelling": "North"
+        }
+      ],
+      "identifier": {
+        "interfaceLanguage": "c",
+        "precise": "c:@E@Direction@North"
+      },
+      "kind": {
+        "displayName": "Enum Case",
+        "identifier": "c.enum.case"
+      },
+      "location": {
+        "character": 3,
+        "line": 11,
+        "uri": "file://INPUT_DIR/input.c"
+      },
+      "names": {
+        "subHeading": [
+          {
+            "kind": "identifier",
+            "spelling": "North"
+          }
+        ],
+        "title": "North"
+      }
+    },
+    {
+      "declarationFragments": [
+        {
+          "kind": "identifier",
+          "spelling": "East"
+        }
+      ],
+      "identifier": {
+        "interfaceLanguage": "c",
+        "precise": "c:@E@Direction@East"
+      },
+      "kind": {
+        "displayName": "Enum Case",
+        "identifier": "c.enum.case"
+      },
+      "location": {
+        "character": 3,
+        "line": 12,
+        "uri": "file://INPUT_DIR/input.c"
+      },
+      "names": {
+        "subHeading": [
+          {
+            "kind": "identifier",
+            "spelling": "East"
+          }
+        ],
+        "title": "East"
+      }
+    },
+    {
+      "declarationFragments": [
+        {
+          "kind": "identifier",
+          "spelling": "South"
+        }
+      ],
+      "identifier": {
+        "interfaceLanguage": "c",
+        "precise": "c:@E@Direction@South"
+      },
+      "kind": {
+        "displayName": "Enum Case",
+        "identifier": "c.enum.case"
+      },
+      "location": {
+        "character": 3,
+        "line": 13,
+        "uri": "file://INPUT_DIR/input.c"
+      },
+      "names": {
+        "subHeading": [
+          {
+            "kind": "identifier",
+            "spelling": "South"
+          }
+        ],
+        "title": "South"
+      }
+    },
+    {
+      "declarationFragments": [
+        {
+          "kind": "identifier",
+          "spelling": "West"
+        }
+      ],
+      "identifier": {
+        "interfaceLanguage": "c",
+        "precise": "c:@E@Direction@West"
+      },
+      "kind": {
+        "displayName": "Enum Case",
+        "identifier": "c.enum.case"
+      },
+      "location": {
+        "character": 3,
+        "line": 14,
+        "uri": "file://INPUT_DIR/input.c"
+      },
+      "names": {
+        "subHeading": [
+          {
+            "kind": "identifier",
+            "spelling": "West"
+          }
+        ],
+        "title": "West"
+      }
+    }
+  ]
+}
Index: clang/lib/SymbolGraph/Serialization.cpp
===================================================================
--- clang/lib/SymbolGraph/Serialization.cpp
+++ clang/lib/SymbolGraph/Serialization.cpp
@@ -225,17 +225,21 @@
 // SymbolGraph: Symbol::kind
 static Object serializeSymbolKind(const APIRecord &Record,
                                   const LangOptions &LangOpts) {
+  auto AddLangPrefix = [&LangOpts](StringRef S) -> std::string {
+    return (getLanguageName(LangOpts) + "." + S).str();
+  };
+
   Object Kind;
   switch (Record.getKind()) {
-  case APIRecord::RK_Global:
+  case APIRecord::RK_Global: {
     auto *GR = dyn_cast<GlobalRecord>(&Record);
     switch (GR->GlobalKind) {
     case GVKind::Function:
-      Kind["identifier"] = (getLanguageName(LangOpts) + ".func").str();
+      Kind["identifier"] = AddLangPrefix("func");
       Kind["displayName"] = "Function";
       break;
     case GVKind::Variable:
-      Kind["identifier"] = (getLanguageName(LangOpts) + ".var").str();
+      Kind["identifier"] = AddLangPrefix("var");
       Kind["displayName"] = "Global Variable";
       break;
     case GVKind::Unknown:
@@ -244,6 +248,15 @@
     }
     break;
   }
+  case APIRecord::RK_EnumConstant:
+    Kind["identifier"] = AddLangPrefix("enum.case");
+    Kind["displayName"] = "Enum Case";
+    break;
+  case APIRecord::RK_Enum:
+    Kind["identifier"] = AddLangPrefix("enum");
+    Kind["displayName"] = "Enum";
+    break;
+  }
 
   return Kind;
 }
@@ -297,6 +310,21 @@
   return Obj;
 }
 
+void Serializer::serializeRelationship(RelationshipKind Kind,
+                                       const APIRecord &Source,
+                                       const APIRecord &Target) {
+  Object Relationship;
+  Relationship["source"] = Source.USR;
+  Relationship["target"] = Target.USR;
+  switch (Kind) {
+  case RelationshipKind::MemberOf:
+    Relationship["kind"] = "memberOf";
+    break;
+  }
+
+  Relationships.emplace_back(std::move(Relationship));
+}
+
 void Serializer::serializeGlobalRecord(const GlobalRecord &Record) {
   auto Obj = serializeAPIRecord(Record);
   if (!Obj)
@@ -309,6 +337,23 @@
   Symbols.emplace_back(std::move(*Obj));
 }
 
+void Serializer::serializeEnumRecord(const EnumRecord &Record) {
+  auto Enum = serializeAPIRecord(Record);
+  if (!Enum)
+    return;
+
+  Symbols.emplace_back(std::move(*Enum));
+
+  for (const auto &Constant : Record.Constants) {
+    auto EnumConstant = serializeAPIRecord(*Constant);
+    if (!EnumConstant)
+      continue;
+
+    Symbols.emplace_back(std::move(*EnumConstant));
+    serializeRelationship(RelationshipKind::MemberOf, *Constant, Record);
+  }
+}
+
 Object Serializer::serialize() {
   Object Root;
   serializeObject(Root, "metadata", serializeMetadata());
@@ -317,6 +362,9 @@
   for (const auto &Global : API.getGlobals())
     serializeGlobalRecord(*Global.second);
 
+  for (const auto &Enum : API.getEnums())
+    serializeEnumRecord(*Enum.second);
+
   Root["symbols"] = std::move(Symbols);
   Root["relationhips"] = std::move(Relationships);
 
Index: clang/lib/SymbolGraph/ExtractAPIConsumer.cpp
===================================================================
--- clang/lib/SymbolGraph/ExtractAPIConsumer.cpp
+++ clang/lib/SymbolGraph/ExtractAPIConsumer.cpp
@@ -134,6 +134,36 @@
     return true;
   }
 
+  bool VisitEnumDecl(const EnumDecl *Decl) {
+    if (!Decl->isComplete())
+      return true;
+
+    // Skip forward declaration.
+    if (!Decl->isThisDeclarationADefinition())
+      return true;
+
+    StringRef Name = Decl->getName();
+    StringRef USR = API.recordUSR(Decl);
+    PresumedLoc Loc =
+        Context.getSourceManager().getPresumedLoc(Decl->getLocation());
+    AvailabilityInfo Availability = getAvailability(Decl);
+    DocComment Comment;
+    if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
+      Comment = RawComment->getFormattedLines(Context.getSourceManager(),
+                                              Context.getDiagnostics());
+    DeclarationFragments Declaration =
+        DeclarationFragmentsBuilder::getFragmentsForEnum(Decl);
+    DeclarationFragments SubHeading =
+        DeclarationFragmentsBuilder::getSubHeading(Decl);
+
+    EnumRecord *EnumRecord = API.addEnum(Name, USR, Loc, Availability, Comment,
+                                         Declaration, SubHeading);
+
+    recordEnumConstants(EnumRecord, Decl->enumerators());
+
+    return true;
+  }
+
 private:
   AvailabilityInfo getAvailability(const Decl *D) const {
     StringRef PlatformName = Context.getTargetInfo().getPlatformName();
@@ -164,6 +194,28 @@
     return Availability;
   }
 
+  void recordEnumConstants(EnumRecord *EnumRecord,
+                           const EnumDecl::enumerator_range Constants) {
+    for (const auto *Constant : Constants) {
+      StringRef Name = Constant->getName();
+      StringRef USR = API.recordUSR(Constant);
+      PresumedLoc Loc =
+          Context.getSourceManager().getPresumedLoc(Constant->getLocation());
+      AvailabilityInfo Availability = getAvailability(Constant);
+      DocComment Comment;
+      if (auto *RawComment = Context.getRawCommentForDeclNoCache(Constant))
+        Comment = RawComment->getFormattedLines(Context.getSourceManager(),
+                                                Context.getDiagnostics());
+      DeclarationFragments Declaration =
+          DeclarationFragmentsBuilder::getFragmentsForEnumConstant(Constant);
+      DeclarationFragments SubHeading =
+          DeclarationFragmentsBuilder::getSubHeading(Constant);
+
+      API.addEnumConstant(EnumRecord, Name, USR, Loc, Availability, Comment,
+                          Declaration, SubHeading);
+    }
+  }
+
   ASTContext &Context;
   APISet API;
 };
Index: clang/lib/SymbolGraph/DeclarationFragments.cpp
===================================================================
--- clang/lib/SymbolGraph/DeclarationFragments.cpp
+++ clang/lib/SymbolGraph/DeclarationFragments.cpp
@@ -399,6 +399,35 @@
   return Fragments;
 }
 
+DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant(
+    const EnumConstantDecl *EnumConstDecl) {
+  DeclarationFragments Fragments;
+  return Fragments.append(EnumConstDecl->getName(),
+                          DeclarationFragments::FragmentKind::Identifier);
+}
+
+DeclarationFragments
+DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {
+  // TODO: After we support typedef records, if there's a typedef for this enum
+  // just use the declaration fragments of the typedef decl.
+
+  DeclarationFragments Fragments, After;
+  Fragments.append("enum", DeclarationFragments::FragmentKind::Keyword);
+
+  if (!EnumDecl->getName().empty())
+    Fragments.appendSpace().append(
+        EnumDecl->getName(), DeclarationFragments::FragmentKind::Identifier);
+
+  QualType IntegerType = EnumDecl->getIntegerType();
+  if (!IntegerType.isNull())
+    Fragments.append(": ", DeclarationFragments::FragmentKind::Text)
+        .append(
+            getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After))
+        .append(std::move(After));
+
+  return Fragments;
+}
+
 FunctionSignature
 DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *Func) {
   FunctionSignature Signature;
Index: clang/lib/SymbolGraph/API.cpp
===================================================================
--- clang/lib/SymbolGraph/API.cpp
+++ clang/lib/SymbolGraph/API.cpp
@@ -59,6 +59,30 @@
                    Comment, Fragments, SubHeading, Signature);
 }
 
+EnumConstantRecord *APISet::addEnumConstant(
+    EnumRecord *Enum, StringRef Name, StringRef USR, PresumedLoc Loc,
+    const AvailabilityInfo &Availability, const DocComment &Comment,
+    DeclarationFragments Declaration, DeclarationFragments SubHeading) {
+  EnumConstantRecord *Record = new (Allocator) EnumConstantRecord{
+      Name, USR, Loc, Availability, Comment, Declaration, SubHeading};
+  Enum->Constants.push_back(Record);
+  return Record;
+}
+
+EnumRecord *APISet::addEnum(StringRef Name, StringRef USR, PresumedLoc Loc,
+                            const AvailabilityInfo &Availability,
+                            const DocComment &Comment,
+                            DeclarationFragments Declaration,
+                            DeclarationFragments SubHeading) {
+  auto Result = Enums.insert({Name, nullptr});
+  if (Result.second) {
+    EnumRecord *Record = new (Allocator) EnumRecord{
+        Name, USR, Loc, Availability, Comment, Declaration, SubHeading};
+    Result.first->second = Record;
+  }
+  return Result.first->second;
+}
+
 StringRef APISet::recordUSR(const Decl *D) {
   SmallString<128> USR;
   index::generateUSRForDecl(D, USR);
Index: clang/include/clang/SymbolGraph/Serialization.h
===================================================================
--- clang/include/clang/SymbolGraph/Serialization.h
+++ clang/include/clang/SymbolGraph/Serialization.h
@@ -36,11 +36,19 @@
   Object serialize();
   void serialize(raw_ostream &os);
 
+  enum RelationshipKind {
+    MemberOf,
+  };
+
 private:
+  void serializeGlobalRecord(const GlobalRecord &Record);
+  void serializeEnumRecord(const EnumRecord &Record);
+
   Object serializeMetadata() const;
   Object serializeModule() const;
   Optional<Object> serializeAPIRecord(const APIRecord &Record) const;
-  void serializeGlobalRecord(const GlobalRecord &Record);
+  void serializeRelationship(RelationshipKind Kind, const APIRecord &Source,
+                             const APIRecord &Target);
 
   bool shouldSkip(const APIRecord &Record) const;
 
Index: clang/include/clang/SymbolGraph/DeclarationFragments.h
===================================================================
--- clang/include/clang/SymbolGraph/DeclarationFragments.h
+++ clang/include/clang/SymbolGraph/DeclarationFragments.h
@@ -117,6 +117,10 @@
 public:
   static DeclarationFragments getFragmentsForVar(const VarDecl *);
   static DeclarationFragments getFragmentsForFunction(const FunctionDecl *);
+  static DeclarationFragments
+  getFragmentsForEnumConstant(const EnumConstantDecl *);
+  static DeclarationFragments getFragmentsForEnum(const EnumDecl *);
+
   static DeclarationFragments getSubHeading(const NamedDecl *);
   static FunctionSignature getFunctionSignature(const FunctionDecl *);
 
Index: clang/include/clang/SymbolGraph/API.h
===================================================================
--- clang/include/clang/SymbolGraph/API.h
+++ clang/include/clang/SymbolGraph/API.h
@@ -43,6 +43,8 @@
   /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
   enum RecordKind {
     RK_Global,
+    RK_EnumConstant,
+    RK_Enum,
   };
 
 private:
@@ -88,6 +90,34 @@
   }
 };
 
+struct EnumConstantRecord : APIRecord {
+  EnumConstantRecord(StringRef Name, StringRef USR, PresumedLoc Loc,
+                     const AvailabilityInfo &Availability,
+                     const DocComment &Comment,
+                     DeclarationFragments Declaration,
+                     DeclarationFragments SubHeading)
+      : APIRecord(RK_EnumConstant, Name, USR, Loc, Availability,
+                  LinkageInfo::none(), Comment, Declaration, SubHeading) {}
+
+  static bool classof(const APIRecord *Record) {
+    return Record->getKind() == RK_EnumConstant;
+  }
+};
+
+struct EnumRecord : APIRecord {
+  SmallVector<EnumConstantRecord *> Constants;
+
+  EnumRecord(StringRef Name, StringRef USR, PresumedLoc Loc,
+             const AvailabilityInfo &Availability, const DocComment &Comment,
+             DeclarationFragments Declaration, DeclarationFragments SubHeading)
+      : APIRecord(RK_Enum, Name, USR, Loc, Availability, LinkageInfo::none(),
+                  Comment, Declaration, SubHeading) {}
+
+  static bool classof(const APIRecord *Record) {
+    return Record->getKind() == RK_Enum;
+  }
+};
+
 class APISet {
 public:
   APISet(const llvm::Triple &Target, const LangOptions &LangOpts)
@@ -116,13 +146,28 @@
                             DeclarationFragments SubHeading,
                             FunctionSignature Signature);
 
+  EnumConstantRecord *addEnumConstant(EnumRecord *Enum, StringRef Name,
+                                      StringRef USR, PresumedLoc Loc,
+                                      const AvailabilityInfo &Availability,
+                                      const DocComment &Comment,
+                                      DeclarationFragments Declaration,
+                                      DeclarationFragments SubHeading);
+
+  EnumRecord *addEnum(StringRef Name, StringRef USR, PresumedLoc Loc,
+                      const AvailabilityInfo &Availability,
+                      const DocComment &Comment,
+                      DeclarationFragments Declaration,
+                      DeclarationFragments SubHeading);
+
   StringRef recordUSR(const Decl *D);
   StringRef copyString(StringRef String, llvm::BumpPtrAllocator &Allocator);
   StringRef copyString(StringRef String);
 
   using GlobalRecordMap = llvm::MapVector<StringRef, GlobalRecord *>;
+  using EnumRecordMap = llvm::MapVector<StringRef, EnumRecord *>;
 
   const GlobalRecordMap &getGlobals() const { return Globals; }
+  const EnumRecordMap &getEnums() const { return Enums; }
 
 private:
   llvm::BumpPtrAllocator Allocator;
@@ -130,6 +175,7 @@
   const LangOptions LangOpts;
 
   GlobalRecordMap Globals;
+  EnumRecordMap Enums;
 };
 
 } // namespace symbolgraph
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to