[clang] 71b4c22 - [clang][extract-api] Add enum support
Zixu Wang via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 23 09:42:45 PDT 2022
Author: Zixu Wang
Date: 2022-03-23T09:41:21-07:00
New Revision: 71b4c22612a06c950d31db83a45dee7412a64c64
URL: https://github.com/llvm/llvm-project/commit/71b4c22612a06c950d31db83a45dee7412a64c64
DIFF: https://github.com/llvm/llvm-project/commit/71b4c22612a06c950d31db83a45dee7412a64c64.diff
LOG: [clang][extract-api] Add enum support
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
Depends on D122160
Differential Revision: https://reviews.llvm.org/D121873
Added:
clang/test/ExtractAPI/enum.c
Modified:
clang/include/clang/ExtractAPI/API.h
clang/include/clang/ExtractAPI/DeclarationFragments.h
clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
clang/lib/ExtractAPI/API.cpp
clang/lib/ExtractAPI/DeclarationFragments.cpp
clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h
index 5ba3cf7268d88..52b78d9188a1c 100644
--- a/clang/include/clang/ExtractAPI/API.h
+++ b/clang/include/clang/ExtractAPI/API.h
@@ -30,6 +30,25 @@
#include "llvm/Support/Casting.h"
#include <memory>
+namespace {
+
+/// \brief A custom deleter used for ``std::unique_ptr`` to APIRecords stored
+/// in the BumpPtrAllocator.
+///
+/// \tparam T the exact type of the APIRecord subclass.
+template <typename T> struct UniquePtrBumpPtrAllocatorDeleter {
+ void operator()(T *Instance) { Instance->~T(); }
+};
+
+/// A unique pointer to an APIRecord stored in the BumpPtrAllocator.
+///
+/// \tparam T the exact type of the APIRecord subclass.
+template <typename T>
+using APIRecordUniquePtr =
+ std::unique_ptr<T, UniquePtrBumpPtrAllocatorDeleter<T>>;
+
+} // anonymous namespace
+
namespace clang {
namespace extractapi {
@@ -73,6 +92,8 @@ struct APIRecord {
/// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
enum RecordKind {
RK_Global,
+ RK_EnumConstant,
+ RK_Enum,
};
private:
@@ -125,6 +146,36 @@ struct GlobalRecord : APIRecord {
virtual void anchor();
};
+/// This holds information associated with enum constants.
+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;
+ }
+};
+
+/// This holds information associated with enums.
+struct EnumRecord : APIRecord {
+ SmallVector<APIRecordUniquePtr<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;
+ }
+};
+
/// APISet holds the set of API records collected from given inputs.
class APISet {
public:
@@ -166,28 +217,41 @@ class APISet {
DeclarationFragments SubHeading,
FunctionSignature Signature);
-private:
- /// \brief A custom deleter used for ``std::unique_ptr`` to APIRecords stored
- /// in the BumpPtrAllocator.
+ /// Create and add an enum constant record into the API set.
///
- /// \tparam T the exact type of the APIRecord subclass.
- template <typename T> struct UniquePtrBumpPtrAllocatorDeleter {
- void operator()(T *Instance) { Instance->~T(); }
- };
-
-public:
- /// A unique pointer to an APIRecord stored in the BumpPtrAllocator.
+ /// Note: the caller is responsible for keeping the StringRef \p Name and
+ /// \p USR alive. APISet::copyString provides a way to copy strings into
+ /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
+ /// to generate the USR for \c D and keep it alive in APISet.
+ EnumConstantRecord *addEnumConstant(EnumRecord *Enum, StringRef Name,
+ StringRef USR, PresumedLoc Loc,
+ const AvailabilityInfo &Availability,
+ const DocComment &Comment,
+ DeclarationFragments Declaration,
+ DeclarationFragments SubHeading);
+
+ /// Create and add an enum record into the API set.
///
- /// \tparam T the exact type of the APIRecord subclass.
- template <typename T>
- using APIRecordUniquePtr =
- std::unique_ptr<T, UniquePtrBumpPtrAllocatorDeleter<T>>;
+ /// Note: the caller is responsible for keeping the StringRef \p Name and
+ /// \p USR alive. APISet::copyString provides a way to copy strings into
+ /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
+ /// to generate the USR for \c D and keep it alive in APISet.
+ EnumRecord *addEnum(StringRef Name, StringRef USR, PresumedLoc Loc,
+ const AvailabilityInfo &Availability,
+ const DocComment &Comment,
+ DeclarationFragments Declaration,
+ DeclarationFragments SubHeading);
/// A map to store the set of GlobalRecord%s with the declaration name as the
/// key.
using GlobalRecordMap =
llvm::MapVector<StringRef, APIRecordUniquePtr<GlobalRecord>>;
+ /// A map to store the set of EnumRecord%s with the declaration name as the
+ /// key.
+ using EnumRecordMap =
+ llvm::MapVector<StringRef, APIRecordUniquePtr<EnumRecord>>;
+
/// Get the target triple for the ExtractAPI invocation.
const llvm::Triple &getTarget() const { return Target; }
@@ -195,6 +259,7 @@ class APISet {
const LangOptions &getLangOpts() const { return LangOpts; }
const GlobalRecordMap &getGlobals() const { return Globals; }
+ const EnumRecordMap &getEnums() const { return Enums; }
/// Generate and store the USR of declaration \p D.
///
@@ -219,6 +284,7 @@ class APISet {
const LangOptions LangOpts;
GlobalRecordMap Globals;
+ EnumRecordMap Enums;
};
} // namespace extractapi
diff --git a/clang/include/clang/ExtractAPI/DeclarationFragments.h b/clang/include/clang/ExtractAPI/DeclarationFragments.h
index 17375efd12c77..7e76a57a48189 100644
--- a/clang/include/clang/ExtractAPI/DeclarationFragments.h
+++ b/clang/include/clang/ExtractAPI/DeclarationFragments.h
@@ -188,6 +188,14 @@ class DeclarationFragmentsBuilder {
/// Build DeclarationFragments for a function declaration FunctionDecl.
static DeclarationFragments getFragmentsForFunction(const FunctionDecl *);
+ /// Build DeclarationFragments for an enum constant declaration
+ /// EnumConstantDecl.
+ static DeclarationFragments
+ getFragmentsForEnumConstant(const EnumConstantDecl *);
+
+ /// Build DeclarationFragments for an enum declaration EnumDecl.
+ static DeclarationFragments getFragmentsForEnum(const EnumDecl *);
+
/// Build sub-heading fragments for a NamedDecl.
static DeclarationFragments getSubHeading(const NamedDecl *);
diff --git a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
index 11c84c1e205d6..2423f511480d4 100644
--- a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
+++ b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
@@ -56,6 +56,17 @@ class SymbolGraphSerializer : public APISerializer {
/// write out the serialized JSON object to \p os.
void serialize(raw_ostream &os) override;
+ /// The kind of a relationship between two symbols.
+ enum RelationshipKind {
+ /// The source symbol is a member of the target symbol.
+ /// For example enum constants are members of the enum, class/instance
+ /// methods are members of the class, etc.
+ MemberOf,
+ };
+
+ /// Get the string representation of the relationship kind.
+ static StringRef getRelationshipString(RelationshipKind Kind);
+
private:
/// Synthesize the metadata section of the Symbol Graph format.
///
@@ -86,9 +97,19 @@ class SymbolGraphSerializer : public APISerializer {
/// containing common symbol information of \p Record.
Optional<Object> serializeAPIRecord(const APIRecord &Record) const;
+ /// Serialize the \p Kind relationship between \p Source and \p Target.
+ ///
+ /// Record the relationship between the two symbols in
+ /// SymbolGraphSerializer::Relationships.
+ void serializeRelationship(RelationshipKind Kind, const APIRecord &Source,
+ const APIRecord &Target);
+
/// Serialize a global record.
void serializeGlobalRecord(const GlobalRecord &Record);
+ /// Serialize an enum record.
+ void serializeEnumRecord(const EnumRecord &Record);
+
public:
SymbolGraphSerializer(const APISet &API, StringRef ProductName,
APISerializerOption Options = {})
diff --git a/clang/lib/ExtractAPI/API.cpp b/clang/lib/ExtractAPI/API.cpp
index 45eef3d1e9529..fd9e92cc7b2bf 100644
--- a/clang/lib/ExtractAPI/API.cpp
+++ b/clang/lib/ExtractAPI/API.cpp
@@ -59,6 +59,31 @@ APISet::addFunction(StringRef Name, StringRef USR, PresumedLoc Loc,
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) {
+ auto Record =
+ APIRecordUniquePtr<EnumConstantRecord>(new (Allocator) EnumConstantRecord{
+ Name, USR, Loc, Availability, Comment, Declaration, SubHeading});
+ return Enum->Constants.emplace_back(std::move(Record)).get();
+}
+
+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) {
+ // Create the record if it does not already exist.
+ auto Record = APIRecordUniquePtr<EnumRecord>(new (Allocator) EnumRecord{
+ Name, USR, Loc, Availability, Comment, Declaration, SubHeading});
+ Result.first->second = std::move(Record);
+ }
+ return Result.first->second.get();
+}
+
StringRef APISet::recordUSR(const Decl *D) {
SmallString<128> USR;
index::generateUSRForDecl(D, USR);
diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp
index d5e03832f80e1..daa01c7dcd13b 100644
--- a/clang/lib/ExtractAPI/DeclarationFragments.cpp
+++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp
@@ -401,6 +401,35 @@ DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
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;
diff --git a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
index 754c3c1089b62..9c8adcf9347ba 100644
--- a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
+++ b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
@@ -145,6 +145,40 @@ class ExtractAPIVisitor : public RecursiveASTVisitor<ExtractAPIVisitor> {
return true;
}
+ bool VisitEnumDecl(const EnumDecl *Decl) {
+ if (!Decl->isComplete())
+ return true;
+
+ // Skip forward declaration.
+ if (!Decl->isThisDeclarationADefinition())
+ return true;
+
+ // Collect symbol information.
+ 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());
+
+ // Build declaration fragments and sub-heading for the enum.
+ DeclarationFragments Declaration =
+ DeclarationFragmentsBuilder::getFragmentsForEnum(Decl);
+ DeclarationFragments SubHeading =
+ DeclarationFragmentsBuilder::getSubHeading(Decl);
+
+ EnumRecord *EnumRecord = API.addEnum(Name, USR, Loc, Availability, Comment,
+ Declaration, SubHeading);
+
+ // Now collect information about the enumerators in this enum.
+ recordEnumConstants(EnumRecord, Decl->enumerators());
+
+ return true;
+ }
+
private:
/// Get availability information of the declaration \p D.
AvailabilityInfo getAvailability(const Decl *D) const {
@@ -177,6 +211,33 @@ class ExtractAPIVisitor : public RecursiveASTVisitor<ExtractAPIVisitor> {
return Availability;
}
+ /// Collect API information for the enum constants and associate with the
+ /// parent enum.
+ void recordEnumConstants(EnumRecord *EnumRecord,
+ const EnumDecl::enumerator_range Constants) {
+ for (const auto *Constant : Constants) {
+ // Collect symbol information.
+ 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());
+
+ // Build declaration fragments and sub-heading for the enum constant.
+ DeclarationFragments Declaration =
+ DeclarationFragmentsBuilder::getFragmentsForEnumConstant(Constant);
+ DeclarationFragments SubHeading =
+ DeclarationFragmentsBuilder::getSubHeading(Constant);
+
+ API.addEnumConstant(EnumRecord, Name, USR, Loc, Availability, Comment,
+ Declaration, SubHeading);
+ }
+ }
+
ASTContext &Context;
APISet API;
};
diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
index f262aab418d33..574ea451e276c 100644
--- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
+++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
@@ -336,17 +336,21 @@ Object serializeNames(const APIRecord &Record) {
/// the kind, and a \c displayName for rendering human-readable names.
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:
@@ -355,6 +359,15 @@ Object serializeSymbolKind(const APIRecord &Record,
}
break;
}
+ case APIRecord::RK_EnumConstant:
+ Kind["identifier"] = AddLangPrefix("enum.case");
+ Kind["displayName"] = "Enumeration Case";
+ break;
+ case APIRecord::RK_Enum:
+ Kind["identifier"] = AddLangPrefix("enum");
+ Kind["displayName"] = "Enumeration";
+ break;
+ }
return Kind;
}
@@ -413,6 +426,25 @@ SymbolGraphSerializer::serializeAPIRecord(const APIRecord &Record) const {
return Obj;
}
+StringRef SymbolGraphSerializer::getRelationshipString(RelationshipKind Kind) {
+ switch (Kind) {
+ case RelationshipKind::MemberOf:
+ return "memberOf";
+ }
+ llvm_unreachable("Unhandled relationship kind");
+}
+
+void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind,
+ const APIRecord &Source,
+ const APIRecord &Target) {
+ Object Relationship;
+ Relationship["source"] = Source.USR;
+ Relationship["target"] = Target.USR;
+ Relationship["kind"] = getRelationshipString(Kind);
+
+ Relationships.emplace_back(std::move(Relationship));
+}
+
void SymbolGraphSerializer::serializeGlobalRecord(const GlobalRecord &Record) {
auto Obj = serializeAPIRecord(Record);
if (!Obj)
@@ -425,6 +457,23 @@ void SymbolGraphSerializer::serializeGlobalRecord(const GlobalRecord &Record) {
Symbols.emplace_back(std::move(*Obj));
}
+void SymbolGraphSerializer::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 SymbolGraphSerializer::serialize() {
Object Root;
serializeObject(Root, "metadata", serializeMetadata());
@@ -434,6 +483,10 @@ Object SymbolGraphSerializer::serialize() {
for (const auto &Global : API.getGlobals())
serializeGlobalRecord(*Global.second);
+ // Serialize enum records in the API set.
+ for (const auto &Enum : API.getEnums())
+ serializeEnumRecord(*Enum.second);
+
Root["symbols"] = std::move(Symbols);
Root["relationhips"] = std::move(Relationships);
diff --git a/clang/test/ExtractAPI/enum.c b/clang/test/ExtractAPI/enum.c
new file mode 100644
index 0000000000000..f3b5cc8e08c74
--- /dev/null
+++ b/clang/test/ExtractAPI/enum.c
@@ -0,0 +1,505 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: sed -e "s at INPUT_DIR@%/t at g" %t/reference.output.json.in >> \
+// RUN: %t/reference.output.json
+// RUN: %clang -extract-api -target arm64-apple-macosx \
+// RUN: %t/input.h -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.h
+/// 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 at Vehicle@Bicycle",
+ "target": "c:@E at Vehicle"
+ },
+ {
+ "kind": "memberOf",
+ "source": "c:@E at Vehicle@Car",
+ "target": "c:@E at Vehicle"
+ },
+ {
+ "kind": "memberOf",
+ "source": "c:@E at Vehicle@Train",
+ "target": "c:@E at Vehicle"
+ },
+ {
+ "kind": "memberOf",
+ "source": "c:@E at Vehicle@Ship",
+ "target": "c:@E at Vehicle"
+ },
+ {
+ "kind": "memberOf",
+ "source": "c:@E at Vehicle@Airplane",
+ "target": "c:@E at Vehicle"
+ },
+ {
+ "kind": "memberOf",
+ "source": "c:@E at Direction@North",
+ "target": "c:@E at Direction"
+ },
+ {
+ "kind": "memberOf",
+ "source": "c:@E at Direction@East",
+ "target": "c:@E at Direction"
+ },
+ {
+ "kind": "memberOf",
+ "source": "c:@E at Direction@South",
+ "target": "c:@E at Direction"
+ },
+ {
+ "kind": "memberOf",
+ "source": "c:@E at Direction@West",
+ "target": "c:@E at 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 at Vehicle"
+ },
+ "kind": {
+ "displayName": "Enumeration",
+ "identifier": "c.enum"
+ },
+ "location": {
+ "character": 6,
+ "line": 2,
+ "uri": "file://INPUT_DIR/input.h"
+ },
+ "names": {
+ "subHeading": [
+ {
+ "kind": "identifier",
+ "spelling": "Vehicle"
+ }
+ ],
+ "title": "Vehicle"
+ }
+ },
+ {
+ "declarationFragments": [
+ {
+ "kind": "identifier",
+ "spelling": "Bicycle"
+ }
+ ],
+ "identifier": {
+ "interfaceLanguage": "c",
+ "precise": "c:@E at Vehicle@Bicycle"
+ },
+ "kind": {
+ "displayName": "Enumeration Case",
+ "identifier": "c.enum.case"
+ },
+ "location": {
+ "character": 3,
+ "line": 3,
+ "uri": "file://INPUT_DIR/input.h"
+ },
+ "names": {
+ "subHeading": [
+ {
+ "kind": "identifier",
+ "spelling": "Bicycle"
+ }
+ ],
+ "title": "Bicycle"
+ }
+ },
+ {
+ "declarationFragments": [
+ {
+ "kind": "identifier",
+ "spelling": "Car"
+ }
+ ],
+ "identifier": {
+ "interfaceLanguage": "c",
+ "precise": "c:@E at Vehicle@Car"
+ },
+ "kind": {
+ "displayName": "Enumeration Case",
+ "identifier": "c.enum.case"
+ },
+ "location": {
+ "character": 3,
+ "line": 4,
+ "uri": "file://INPUT_DIR/input.h"
+ },
+ "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 at Vehicle@Train"
+ },
+ "kind": {
+ "displayName": "Enumeration Case",
+ "identifier": "c.enum.case"
+ },
+ "location": {
+ "character": 3,
+ "line": 5,
+ "uri": "file://INPUT_DIR/input.h"
+ },
+ "names": {
+ "subHeading": [
+ {
+ "kind": "identifier",
+ "spelling": "Train"
+ }
+ ],
+ "title": "Train"
+ }
+ },
+ {
+ "declarationFragments": [
+ {
+ "kind": "identifier",
+ "spelling": "Ship"
+ }
+ ],
+ "identifier": {
+ "interfaceLanguage": "c",
+ "precise": "c:@E at Vehicle@Ship"
+ },
+ "kind": {
+ "displayName": "Enumeration Case",
+ "identifier": "c.enum.case"
+ },
+ "location": {
+ "character": 3,
+ "line": 6,
+ "uri": "file://INPUT_DIR/input.h"
+ },
+ "names": {
+ "subHeading": [
+ {
+ "kind": "identifier",
+ "spelling": "Ship"
+ }
+ ],
+ "title": "Ship"
+ }
+ },
+ {
+ "declarationFragments": [
+ {
+ "kind": "identifier",
+ "spelling": "Airplane"
+ }
+ ],
+ "identifier": {
+ "interfaceLanguage": "c",
+ "precise": "c:@E at Vehicle@Airplane"
+ },
+ "kind": {
+ "displayName": "Enumeration Case",
+ "identifier": "c.enum.case"
+ },
+ "location": {
+ "character": 3,
+ "line": 7,
+ "uri": "file://INPUT_DIR/input.h"
+ },
+ "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 at Direction"
+ },
+ "kind": {
+ "displayName": "Enumeration",
+ "identifier": "c.enum"
+ },
+ "location": {
+ "character": 6,
+ "line": 10,
+ "uri": "file://INPUT_DIR/input.h"
+ },
+ "names": {
+ "subHeading": [
+ {
+ "kind": "identifier",
+ "spelling": "Direction"
+ }
+ ],
+ "title": "Direction"
+ }
+ },
+ {
+ "declarationFragments": [
+ {
+ "kind": "identifier",
+ "spelling": "North"
+ }
+ ],
+ "identifier": {
+ "interfaceLanguage": "c",
+ "precise": "c:@E at Direction@North"
+ },
+ "kind": {
+ "displayName": "Enumeration Case",
+ "identifier": "c.enum.case"
+ },
+ "location": {
+ "character": 3,
+ "line": 11,
+ "uri": "file://INPUT_DIR/input.h"
+ },
+ "names": {
+ "subHeading": [
+ {
+ "kind": "identifier",
+ "spelling": "North"
+ }
+ ],
+ "title": "North"
+ }
+ },
+ {
+ "declarationFragments": [
+ {
+ "kind": "identifier",
+ "spelling": "East"
+ }
+ ],
+ "identifier": {
+ "interfaceLanguage": "c",
+ "precise": "c:@E at Direction@East"
+ },
+ "kind": {
+ "displayName": "Enumeration Case",
+ "identifier": "c.enum.case"
+ },
+ "location": {
+ "character": 3,
+ "line": 12,
+ "uri": "file://INPUT_DIR/input.h"
+ },
+ "names": {
+ "subHeading": [
+ {
+ "kind": "identifier",
+ "spelling": "East"
+ }
+ ],
+ "title": "East"
+ }
+ },
+ {
+ "declarationFragments": [
+ {
+ "kind": "identifier",
+ "spelling": "South"
+ }
+ ],
+ "identifier": {
+ "interfaceLanguage": "c",
+ "precise": "c:@E at Direction@South"
+ },
+ "kind": {
+ "displayName": "Enumeration Case",
+ "identifier": "c.enum.case"
+ },
+ "location": {
+ "character": 3,
+ "line": 13,
+ "uri": "file://INPUT_DIR/input.h"
+ },
+ "names": {
+ "subHeading": [
+ {
+ "kind": "identifier",
+ "spelling": "South"
+ }
+ ],
+ "title": "South"
+ }
+ },
+ {
+ "declarationFragments": [
+ {
+ "kind": "identifier",
+ "spelling": "West"
+ }
+ ],
+ "identifier": {
+ "interfaceLanguage": "c",
+ "precise": "c:@E at Direction@West"
+ },
+ "kind": {
+ "displayName": "Enumeration Case",
+ "identifier": "c.enum.case"
+ },
+ "location": {
+ "character": 3,
+ "line": 14,
+ "uri": "file://INPUT_DIR/input.h"
+ },
+ "names": {
+ "subHeading": [
+ {
+ "kind": "identifier",
+ "spelling": "West"
+ }
+ ],
+ "title": "West"
+ }
+ }
+ ]
+}
More information about the cfe-commits
mailing list