[clang][ExtractAPI] Flatten all enum cases from anonymous enums at top level (#93559)
rdar://128863241
This commit is contained in:
parent
93d8d74ae6
commit
fa649df8e5
@ -21,6 +21,7 @@
|
|||||||
#include "clang/AST/DeclTemplate.h"
|
#include "clang/AST/DeclTemplate.h"
|
||||||
#include "clang/AST/ParentMapContext.h"
|
#include "clang/AST/ParentMapContext.h"
|
||||||
#include "clang/AST/RecursiveASTVisitor.h"
|
#include "clang/AST/RecursiveASTVisitor.h"
|
||||||
|
#include "clang/Basic/LLVM.h"
|
||||||
#include "clang/Basic/Module.h"
|
#include "clang/Basic/Module.h"
|
||||||
#include "clang/Basic/SourceManager.h"
|
#include "clang/Basic/SourceManager.h"
|
||||||
#include "clang/Basic/Specifiers.h"
|
#include "clang/Basic/Specifiers.h"
|
||||||
@ -127,7 +128,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
/// Collect API information for the enum constants and associate with the
|
/// Collect API information for the enum constants and associate with the
|
||||||
/// parent enum.
|
/// parent enum.
|
||||||
void recordEnumConstants(EnumRecord *EnumRecord,
|
void recordEnumConstants(SymbolReference Container,
|
||||||
const EnumDecl::enumerator_range Constants);
|
const EnumDecl::enumerator_range Constants);
|
||||||
|
|
||||||
/// Collect API information for the Objective-C methods and associate with the
|
/// Collect API information for the Objective-C methods and associate with the
|
||||||
@ -248,12 +249,8 @@ protected:
|
|||||||
clang::index::generateUSRForDecl(Tag, TagUSR);
|
clang::index::generateUSRForDecl(Tag, TagUSR);
|
||||||
if (auto *Record = llvm::dyn_cast_if_present<TagRecord>(
|
if (auto *Record = llvm::dyn_cast_if_present<TagRecord>(
|
||||||
API.findRecordForUSR(TagUSR))) {
|
API.findRecordForUSR(TagUSR))) {
|
||||||
if (Record->IsEmbeddedInVarDeclarator) {
|
if (Record->IsEmbeddedInVarDeclarator)
|
||||||
NewRecordContext->stealRecordChain(*Record);
|
NewRecordContext->stealRecordChain(*Record);
|
||||||
auto *NewRecord = cast<APIRecord>(NewRecordContext);
|
|
||||||
if (NewRecord->Comment.empty())
|
|
||||||
NewRecord->Comment = Record->Comment;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -394,17 +391,6 @@ bool ExtractAPIVisitorBase<Derived>::VisitEnumDecl(const EnumDecl *Decl) {
|
|||||||
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
|
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
SmallString<128> QualifiedNameBuffer;
|
|
||||||
// Collect symbol information.
|
|
||||||
StringRef Name = Decl->getName();
|
|
||||||
if (Name.empty())
|
|
||||||
Name = getTypedefName(Decl);
|
|
||||||
if (Name.empty()) {
|
|
||||||
llvm::raw_svector_ostream OS(QualifiedNameBuffer);
|
|
||||||
Decl->printQualifiedName(OS);
|
|
||||||
Name = QualifiedNameBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
SmallString<128> USR;
|
SmallString<128> USR;
|
||||||
index::generateUSRForDecl(Decl, USR);
|
index::generateUSRForDecl(Decl, USR);
|
||||||
PresumedLoc Loc =
|
PresumedLoc Loc =
|
||||||
@ -420,13 +406,29 @@ bool ExtractAPIVisitorBase<Derived>::VisitEnumDecl(const EnumDecl *Decl) {
|
|||||||
DeclarationFragmentsBuilder::getFragmentsForEnum(Decl);
|
DeclarationFragmentsBuilder::getFragmentsForEnum(Decl);
|
||||||
DeclarationFragments SubHeading =
|
DeclarationFragments SubHeading =
|
||||||
DeclarationFragmentsBuilder::getSubHeading(Decl);
|
DeclarationFragmentsBuilder::getSubHeading(Decl);
|
||||||
|
|
||||||
|
// Collect symbol information.
|
||||||
|
SymbolReference ParentContainer;
|
||||||
|
|
||||||
|
if (Decl->hasNameForLinkage()) {
|
||||||
|
StringRef Name = Decl->getName();
|
||||||
|
if (Name.empty())
|
||||||
|
Name = getTypedefName(Decl);
|
||||||
|
|
||||||
auto *ER = API.createRecord<EnumRecord>(
|
auto *ER = API.createRecord<EnumRecord>(
|
||||||
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
|
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
|
||||||
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
|
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
|
||||||
isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl));
|
SubHeading, isInSystemHeader(Decl), false);
|
||||||
|
ParentContainer = SymbolReference(ER);
|
||||||
|
} else {
|
||||||
|
// If this an anonymous enum then the parent scope of the constants is the
|
||||||
|
// top level namespace.
|
||||||
|
ParentContainer = {};
|
||||||
|
}
|
||||||
|
|
||||||
// Now collect information about the enumerators in this enum.
|
// Now collect information about the enumerators in this enum.
|
||||||
getDerivedExtractAPIVisitor().recordEnumConstants(ER, Decl->enumerators());
|
getDerivedExtractAPIVisitor().recordEnumConstants(ParentContainer,
|
||||||
|
Decl->enumerators());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1197,7 +1199,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCCategoryDecl(
|
|||||||
/// parent enum.
|
/// parent enum.
|
||||||
template <typename Derived>
|
template <typename Derived>
|
||||||
void ExtractAPIVisitorBase<Derived>::recordEnumConstants(
|
void ExtractAPIVisitorBase<Derived>::recordEnumConstants(
|
||||||
EnumRecord *EnumRecord, const EnumDecl::enumerator_range Constants) {
|
SymbolReference Container, const EnumDecl::enumerator_range Constants) {
|
||||||
for (const auto *Constant : Constants) {
|
for (const auto *Constant : Constants) {
|
||||||
// Collect symbol information.
|
// Collect symbol information.
|
||||||
StringRef Name = Constant->getName();
|
StringRef Name = Constant->getName();
|
||||||
@ -1218,9 +1220,8 @@ void ExtractAPIVisitorBase<Derived>::recordEnumConstants(
|
|||||||
DeclarationFragmentsBuilder::getSubHeading(Constant);
|
DeclarationFragmentsBuilder::getSubHeading(Constant);
|
||||||
|
|
||||||
API.createRecord<EnumConstantRecord>(
|
API.createRecord<EnumConstantRecord>(
|
||||||
USR, Name, createHierarchyInformationForDecl(*Constant), Loc,
|
USR, Name, Container, Loc, AvailabilityInfo::createFromDecl(Constant),
|
||||||
AvailabilityInfo::createFromDecl(Constant), Comment, Declaration,
|
Comment, Declaration, SubHeading, isInSystemHeader(Constant));
|
||||||
SubHeading, isInSystemHeader(Constant));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1469,7 +1470,17 @@ public:
|
|||||||
|
|
||||||
bool shouldDeclBeIncluded(const Decl *D) const { return true; }
|
bool shouldDeclBeIncluded(const Decl *D) const { return true; }
|
||||||
const RawComment *fetchRawCommentForDecl(const Decl *D) const {
|
const RawComment *fetchRawCommentForDecl(const Decl *D) const {
|
||||||
return this->Context.getRawCommentForDeclNoCache(D);
|
if (const auto *Comment = this->Context.getRawCommentForDeclNoCache(D))
|
||||||
|
return Comment;
|
||||||
|
|
||||||
|
if (const auto *Declarator = dyn_cast<DeclaratorDecl>(D)) {
|
||||||
|
const auto *TagTypeDecl = Declarator->getType()->getAsTagDecl();
|
||||||
|
if (TagTypeDecl && TagTypeDecl->isEmbeddedInDeclarator() &&
|
||||||
|
TagTypeDecl->isCompleteDefinition())
|
||||||
|
return this->Context.getRawCommentForDeclNoCache(TagTypeDecl);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -84,21 +84,15 @@ struct Vehicle {
|
|||||||
// TYPE: "text": "The type of vehicle."
|
// TYPE: "text": "The type of vehicle."
|
||||||
// TYPE: "title": "type"
|
// TYPE: "title": "type"
|
||||||
|
|
||||||
// BICYCLE: "!testRelLabel": "memberOf $ c:@S@Vehicle@E@anonymous_record_no_typedef.c@{{[0-9]+}}@Bicycle $ c:@S@Vehicle@FI@type"
|
|
||||||
// BICYCLE-LABEL: "!testLabel": "c:@S@Vehicle@E@anonymous_record_no_typedef.c@{{[0-9]+}}@Bicycle"
|
// BICYCLE-LABEL: "!testLabel": "c:@S@Vehicle@E@anonymous_record_no_typedef.c@{{[0-9]+}}@Bicycle"
|
||||||
// BICYCLE: "title": "Bicycle"
|
// BICYCLE: "title": "Bicycle"
|
||||||
// BICYCLE: "pathComponents": [
|
// BICYCLE: "pathComponents": [
|
||||||
// BICYCLE-NEXT: "Vehicle",
|
|
||||||
// BICYCLE-NEXT: "type",
|
|
||||||
// BICYCLE-NEXT: "Bicycle"
|
// BICYCLE-NEXT: "Bicycle"
|
||||||
// BICYCLE-NEXT: ]
|
// BICYCLE-NEXT: ]
|
||||||
|
|
||||||
// CAR: "!testRelLabel": "memberOf $ c:@S@Vehicle@E@anonymous_record_no_typedef.c@{{[0-9]+}}@Car $ c:@S@Vehicle@FI@type"
|
|
||||||
// CAR-LABEL: "!testLabel": "c:@S@Vehicle@E@anonymous_record_no_typedef.c@{{[0-9]+}}@Car"
|
// CAR-LABEL: "!testLabel": "c:@S@Vehicle@E@anonymous_record_no_typedef.c@{{[0-9]+}}@Car"
|
||||||
// CAR: "title": "Car"
|
// CAR: "title": "Car"
|
||||||
// CAR: "pathComponents": [
|
// CAR: "pathComponents": [
|
||||||
// CAR-NEXT: "Vehicle",
|
|
||||||
// CAR-NEXT: "type",
|
|
||||||
// CAR-NEXT: "Car"
|
// CAR-NEXT: "Car"
|
||||||
// CAR-NEXT: ]
|
// CAR-NEXT: ]
|
||||||
|
|
||||||
@ -151,32 +145,22 @@ struct Vehicle {
|
|||||||
// NAME-NEXT: ]
|
// NAME-NEXT: ]
|
||||||
};
|
};
|
||||||
|
|
||||||
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GLOBALENUM
|
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GLOBALCASE
|
||||||
|
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GLOBALOTHERCASE
|
||||||
enum {
|
enum {
|
||||||
GlobalCase,
|
GlobalCase,
|
||||||
GlobalOtherCase
|
GlobalOtherCase
|
||||||
};
|
};
|
||||||
// GLOBALENUM-DAG: "!testRelLabel": "memberOf $ c:@Ea@GlobalCase@GlobalCase $ c:@Ea@GlobalCase"
|
// GLOBALCASE-LABEL: "!testLabel": "c:@Ea@GlobalCase@GlobalCase"
|
||||||
// GLOBALENUM-DAG: "!testRelLabel": "memberOf $ c:@Ea@GlobalCase@GlobalOtherCase $ c:@Ea@GlobalCase"
|
// GLOBALCASE: "title": "GlobalCase"
|
||||||
// GLOBALENUM-LABEL: "!testLabel": "c:@Ea@GlobalCase"
|
// GLOBALCASE: "pathComponents": [
|
||||||
// GLOBALENUM: "declarationFragments": [
|
// GLOBALCASE-NEXT: "GlobalCase"
|
||||||
// GLOBALENUM-NEXT: {
|
// GLOBALCASE-NEXT: ]
|
||||||
// GLOBALENUM-NEXT: "kind": "keyword",
|
|
||||||
// GLOBALENUM-NEXT: "spelling": "enum"
|
// GLOBALOTHERCASE-LABEL: "!testLabel": "c:@Ea@GlobalCase@GlobalOtherCase"
|
||||||
// GLOBALENUM-NEXT: },
|
// GLOBALOTHERCASE: "title": "GlobalOtherCase"
|
||||||
// GLOBALENUM-NEXT: {
|
// GLOBALOTHERCASE: "pathComponents": [
|
||||||
// GLOBALENUM-NEXT: "kind": "text",
|
// GLOBALOTHERCASE-NEXT: "GlobalOtherCase"
|
||||||
// GLOBALENUM-NEXT: "spelling": " : "
|
// GLOBALOTHERCASE-NEXT: ]
|
||||||
// GLOBALENUM-NEXT: },
|
|
||||||
// GLOBALENUM-NEXT: {
|
|
||||||
// GLOBALENUM-NEXT: "kind": "typeIdentifier",
|
|
||||||
// GLOBALENUM-NEXT: "preciseIdentifier": "c:i",
|
|
||||||
// GLOBALENUM-NEXT: "spelling": "unsigned int"
|
|
||||||
// GLOBALENUM-NEXT: },
|
|
||||||
// GLOBALENUM-NEXT: {
|
|
||||||
// GLOBALENUM-NEXT: "kind": "text",
|
|
||||||
// GLOBALENUM-NEXT: "spelling": " { ... };"
|
|
||||||
// GLOBALENUM-NEXT: }
|
|
||||||
// GLOBALENUM-NEXT: ]
|
|
||||||
|
|
||||||
// expected-no-diagnostics
|
// expected-no-diagnostics
|
||||||
|
@ -115,18 +115,6 @@ enum {
|
|||||||
"source": "c:@E@Direction@West",
|
"source": "c:@E@Direction@West",
|
||||||
"target": "c:@E@Direction",
|
"target": "c:@E@Direction",
|
||||||
"targetFallback": "Direction"
|
"targetFallback": "Direction"
|
||||||
},
|
|
||||||
{
|
|
||||||
"kind": "memberOf",
|
|
||||||
"source": "c:@Ea@Constant@Constant",
|
|
||||||
"target": "c:@Ea@Constant",
|
|
||||||
"targetFallback": "enum (unnamed)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kind": "memberOf",
|
|
||||||
"source": "c:@Ea@OtherConstant@OtherConstant",
|
|
||||||
"target": "c:@Ea@OtherConstant",
|
|
||||||
"targetFallback": "enum (unnamed)"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"symbols": [
|
"symbols": [
|
||||||
@ -677,55 +665,6 @@ enum {
|
|||||||
"West"
|
"West"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"accessLevel": "public",
|
|
||||||
"declarationFragments": [
|
|
||||||
{
|
|
||||||
"kind": "keyword",
|
|
||||||
"spelling": "enum"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kind": "text",
|
|
||||||
"spelling": " : "
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kind": "typeIdentifier",
|
|
||||||
"preciseIdentifier": "c:i",
|
|
||||||
"spelling": "unsigned int"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kind": "text",
|
|
||||||
"spelling": " { ... };"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"identifier": {
|
|
||||||
"interfaceLanguage": "c",
|
|
||||||
"precise": "c:@Ea@Constant"
|
|
||||||
},
|
|
||||||
"kind": {
|
|
||||||
"displayName": "Enumeration",
|
|
||||||
"identifier": "c.enum"
|
|
||||||
},
|
|
||||||
"location": {
|
|
||||||
"position": {
|
|
||||||
"character": 0,
|
|
||||||
"line": 16
|
|
||||||
},
|
|
||||||
"uri": "file://INPUT_DIR/input.h"
|
|
||||||
},
|
|
||||||
"names": {
|
|
||||||
"navigator": [
|
|
||||||
{
|
|
||||||
"kind": "identifier",
|
|
||||||
"spelling": "enum (unnamed)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"title": "enum (unnamed)"
|
|
||||||
},
|
|
||||||
"pathComponents": [
|
|
||||||
"enum (unnamed)"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"accessLevel": "public",
|
"accessLevel": "public",
|
||||||
"declarationFragments": [
|
"declarationFragments": [
|
||||||
@ -765,59 +704,9 @@ enum {
|
|||||||
"title": "Constant"
|
"title": "Constant"
|
||||||
},
|
},
|
||||||
"pathComponents": [
|
"pathComponents": [
|
||||||
"enum (unnamed)",
|
|
||||||
"Constant"
|
"Constant"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"accessLevel": "public",
|
|
||||||
"declarationFragments": [
|
|
||||||
{
|
|
||||||
"kind": "keyword",
|
|
||||||
"spelling": "enum"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kind": "text",
|
|
||||||
"spelling": " : "
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kind": "typeIdentifier",
|
|
||||||
"preciseIdentifier": "c:i",
|
|
||||||
"spelling": "unsigned int"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kind": "text",
|
|
||||||
"spelling": " { ... };"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"identifier": {
|
|
||||||
"interfaceLanguage": "c",
|
|
||||||
"precise": "c:@Ea@OtherConstant"
|
|
||||||
},
|
|
||||||
"kind": {
|
|
||||||
"displayName": "Enumeration",
|
|
||||||
"identifier": "c.enum"
|
|
||||||
},
|
|
||||||
"location": {
|
|
||||||
"position": {
|
|
||||||
"character": 0,
|
|
||||||
"line": 20
|
|
||||||
},
|
|
||||||
"uri": "file://INPUT_DIR/input.h"
|
|
||||||
},
|
|
||||||
"names": {
|
|
||||||
"navigator": [
|
|
||||||
{
|
|
||||||
"kind": "identifier",
|
|
||||||
"spelling": "enum (unnamed)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"title": "enum (unnamed)"
|
|
||||||
},
|
|
||||||
"pathComponents": [
|
|
||||||
"enum (unnamed)"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"accessLevel": "public",
|
"accessLevel": "public",
|
||||||
"declarationFragments": [
|
"declarationFragments": [
|
||||||
@ -857,7 +746,6 @@ enum {
|
|||||||
"title": "OtherConstant"
|
"title": "OtherConstant"
|
||||||
},
|
},
|
||||||
"pathComponents": [
|
"pathComponents": [
|
||||||
"enum (unnamed)",
|
|
||||||
"OtherConstant"
|
"OtherConstant"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,9 @@ struct LibClangExtractAPIVisitor
|
|||||||
: ExtractAPIVisitor<LibClangExtractAPIVisitor>(Context, API) {}
|
: ExtractAPIVisitor<LibClangExtractAPIVisitor>(Context, API) {}
|
||||||
|
|
||||||
const RawComment *fetchRawCommentForDecl(const Decl *D) const {
|
const RawComment *fetchRawCommentForDecl(const Decl *D) const {
|
||||||
|
if (const auto *Comment = Base::fetchRawCommentForDecl(D))
|
||||||
|
return Comment;
|
||||||
|
|
||||||
return Context.getRawCommentForAnyRedecl(D);
|
return Context.getRawCommentForAnyRedecl(D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user