mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-05-15 02:16:40 +00:00

Anonymous enums that are typedef'd should take on the name of the typedef. Differential Revision: https://reviews.llvm.org/D140010
561 lines
21 KiB
C++
561 lines
21 KiB
C++
//===- ExtractAPI/ExtractAPIVisitor.cpp -------------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
/// This file implements the ExtractAPIVisitor an ASTVisitor to collect API
|
|
/// information.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/ExtractAPI/ExtractAPIVisitor.h"
|
|
|
|
#include "TypedefUnderlyingTypeResolver.h"
|
|
#include "clang/AST/ASTConsumer.h"
|
|
#include "clang/AST/ASTContext.h"
|
|
#include "clang/AST/Decl.h"
|
|
#include "clang/AST/DeclCXX.h"
|
|
#include "clang/AST/ParentMapContext.h"
|
|
#include "clang/AST/RawCommentList.h"
|
|
#include "clang/Basic/SourceLocation.h"
|
|
#include "clang/Basic/SourceManager.h"
|
|
#include "clang/Basic/TargetInfo.h"
|
|
#include "clang/ExtractAPI/API.h"
|
|
#include "clang/ExtractAPI/AvailabilityInfo.h"
|
|
#include "clang/ExtractAPI/DeclarationFragments.h"
|
|
#include "clang/Frontend/ASTConsumers.h"
|
|
#include "clang/Frontend/FrontendOptions.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
using namespace clang;
|
|
using namespace extractapi;
|
|
|
|
namespace {
|
|
|
|
StringRef getTypedefName(const TagDecl *Decl) {
|
|
if (const auto *TypedefDecl = Decl->getTypedefNameForAnonDecl())
|
|
return TypedefDecl->getName();
|
|
|
|
return {};
|
|
}
|
|
|
|
template <class DeclTy>
|
|
bool isInSystemHeader(const ASTContext &Context, const DeclTy *D) {
|
|
return Context.getSourceManager().isInSystemHeader(D->getLocation());
|
|
}
|
|
|
|
} // namespace
|
|
|
|
bool ExtractAPIVisitor::VisitVarDecl(const VarDecl *Decl) {
|
|
// skip function parameters.
|
|
if (isa<ParmVarDecl>(Decl))
|
|
return true;
|
|
|
|
// Skip non-global variables in records (struct/union/class).
|
|
if (Decl->getDeclContext()->isRecord())
|
|
return true;
|
|
|
|
// Skip local variables inside function or method.
|
|
if (!Decl->isDefinedOutsideFunctionOrMethod())
|
|
return true;
|
|
|
|
// If this is a template but not specialization or instantiation, skip.
|
|
if (Decl->getASTContext().getTemplateOrSpecializationInfo(Decl) &&
|
|
Decl->getTemplateSpecializationKind() == TSK_Undeclared)
|
|
return true;
|
|
|
|
if (!LocationChecker(Decl->getLocation()))
|
|
return true;
|
|
|
|
// Collect symbol information.
|
|
StringRef Name = Decl->getName();
|
|
StringRef USR = API.recordUSR(Decl);
|
|
PresumedLoc Loc =
|
|
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
|
|
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
|
|
DocComment Comment;
|
|
if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
|
|
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
|
|
Context.getDiagnostics());
|
|
|
|
// Build declaration fragments and sub-heading for the variable.
|
|
DeclarationFragments Declaration =
|
|
DeclarationFragmentsBuilder::getFragmentsForVar(Decl);
|
|
DeclarationFragments SubHeading =
|
|
DeclarationFragmentsBuilder::getSubHeading(Decl);
|
|
|
|
// Add the global variable record to the API set.
|
|
API.addGlobalVar(Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment,
|
|
Declaration, SubHeading, isInSystemHeader(Context, Decl));
|
|
return true;
|
|
}
|
|
|
|
bool ExtractAPIVisitor::VisitFunctionDecl(const FunctionDecl *Decl) {
|
|
if (const auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
|
|
// Skip member function in class templates.
|
|
if (Method->getParent()->getDescribedClassTemplate() != nullptr)
|
|
return true;
|
|
|
|
// Skip methods in records.
|
|
for (auto P : Context.getParents(*Method)) {
|
|
if (P.get<CXXRecordDecl>())
|
|
return true;
|
|
}
|
|
|
|
// Skip ConstructorDecl and DestructorDecl.
|
|
if (isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method))
|
|
return true;
|
|
}
|
|
|
|
// Skip templated functions.
|
|
switch (Decl->getTemplatedKind()) {
|
|
case FunctionDecl::TK_NonTemplate:
|
|
case FunctionDecl::TK_DependentNonTemplate:
|
|
break;
|
|
case FunctionDecl::TK_MemberSpecialization:
|
|
case FunctionDecl::TK_FunctionTemplateSpecialization:
|
|
if (auto *TemplateInfo = Decl->getTemplateSpecializationInfo()) {
|
|
if (!TemplateInfo->isExplicitInstantiationOrSpecialization())
|
|
return true;
|
|
}
|
|
break;
|
|
case FunctionDecl::TK_FunctionTemplate:
|
|
case FunctionDecl::TK_DependentFunctionTemplateSpecialization:
|
|
return true;
|
|
}
|
|
|
|
if (!LocationChecker(Decl->getLocation()))
|
|
return true;
|
|
|
|
// Collect symbol information.
|
|
StringRef Name = Decl->getName();
|
|
StringRef USR = API.recordUSR(Decl);
|
|
PresumedLoc Loc =
|
|
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
|
|
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
|
|
DocComment Comment;
|
|
if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
|
|
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
|
|
Context.getDiagnostics());
|
|
|
|
// Build declaration fragments, sub-heading, and signature of the function.
|
|
DeclarationFragments Declaration =
|
|
DeclarationFragmentsBuilder::getFragmentsForFunction(Decl);
|
|
DeclarationFragments SubHeading =
|
|
DeclarationFragmentsBuilder::getSubHeading(Decl);
|
|
FunctionSignature Signature =
|
|
DeclarationFragmentsBuilder::getFunctionSignature(Decl);
|
|
|
|
// Add the function record to the API set.
|
|
API.addGlobalFunction(Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment,
|
|
Declaration, SubHeading, Signature,
|
|
isInSystemHeader(Context, Decl));
|
|
return true;
|
|
}
|
|
|
|
bool ExtractAPIVisitor::VisitEnumDecl(const EnumDecl *Decl) {
|
|
if (!Decl->isComplete())
|
|
return true;
|
|
|
|
// Skip forward declaration.
|
|
if (!Decl->isThisDeclarationADefinition())
|
|
return true;
|
|
|
|
if (!LocationChecker(Decl->getLocation()))
|
|
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.str();
|
|
}
|
|
|
|
StringRef USR = API.recordUSR(Decl);
|
|
PresumedLoc Loc =
|
|
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
|
|
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(
|
|
API.copyString(Name), USR, Loc, AvailabilitySet(Decl), Comment,
|
|
Declaration, SubHeading, isInSystemHeader(Context, Decl));
|
|
|
|
// Now collect information about the enumerators in this enum.
|
|
recordEnumConstants(EnumRecord, Decl->enumerators());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ExtractAPIVisitor::VisitRecordDecl(const RecordDecl *Decl) {
|
|
if (!Decl->isCompleteDefinition())
|
|
return true;
|
|
|
|
// Skip C++ structs/classes/unions
|
|
// TODO: support C++ records
|
|
if (isa<CXXRecordDecl>(Decl))
|
|
return true;
|
|
|
|
if (!LocationChecker(Decl->getLocation()))
|
|
return true;
|
|
|
|
// Collect symbol information.
|
|
StringRef Name = Decl->getName();
|
|
if (Name.empty())
|
|
Name = getTypedefName(Decl);
|
|
if (Name.empty())
|
|
return true;
|
|
|
|
StringRef USR = API.recordUSR(Decl);
|
|
PresumedLoc Loc =
|
|
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
|
|
DocComment Comment;
|
|
if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
|
|
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
|
|
Context.getDiagnostics());
|
|
|
|
// Build declaration fragments and sub-heading for the struct.
|
|
DeclarationFragments Declaration =
|
|
DeclarationFragmentsBuilder::getFragmentsForStruct(Decl);
|
|
DeclarationFragments SubHeading =
|
|
DeclarationFragmentsBuilder::getSubHeading(Decl);
|
|
|
|
StructRecord *StructRecord =
|
|
API.addStruct(Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration,
|
|
SubHeading, isInSystemHeader(Context, Decl));
|
|
|
|
// Now collect information about the fields in this struct.
|
|
recordStructFields(StructRecord, Decl->fields());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ExtractAPIVisitor::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *Decl) {
|
|
// Skip forward declaration for classes (@class)
|
|
if (!Decl->isThisDeclarationADefinition())
|
|
return true;
|
|
|
|
if (!LocationChecker(Decl->getLocation()))
|
|
return true;
|
|
|
|
// Collect symbol information.
|
|
StringRef Name = Decl->getName();
|
|
StringRef USR = API.recordUSR(Decl);
|
|
PresumedLoc Loc =
|
|
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
|
|
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
|
|
DocComment Comment;
|
|
if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
|
|
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
|
|
Context.getDiagnostics());
|
|
|
|
// Build declaration fragments and sub-heading for the interface.
|
|
DeclarationFragments Declaration =
|
|
DeclarationFragmentsBuilder::getFragmentsForObjCInterface(Decl);
|
|
DeclarationFragments SubHeading =
|
|
DeclarationFragmentsBuilder::getSubHeading(Decl);
|
|
|
|
// Collect super class information.
|
|
SymbolReference SuperClass;
|
|
if (const auto *SuperClassDecl = Decl->getSuperClass()) {
|
|
SuperClass.Name = SuperClassDecl->getObjCRuntimeNameAsString();
|
|
SuperClass.USR = API.recordUSR(SuperClassDecl);
|
|
}
|
|
|
|
ObjCInterfaceRecord *ObjCInterfaceRecord = API.addObjCInterface(
|
|
Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment, Declaration,
|
|
SubHeading, SuperClass, isInSystemHeader(Context, Decl));
|
|
|
|
// Record all methods (selectors). This doesn't include automatically
|
|
// synthesized property methods.
|
|
recordObjCMethods(ObjCInterfaceRecord, Decl->methods());
|
|
recordObjCProperties(ObjCInterfaceRecord, Decl->properties());
|
|
recordObjCInstanceVariables(ObjCInterfaceRecord, Decl->ivars());
|
|
recordObjCProtocols(ObjCInterfaceRecord, Decl->protocols());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ExtractAPIVisitor::VisitObjCProtocolDecl(const ObjCProtocolDecl *Decl) {
|
|
// Skip forward declaration for protocols (@protocol).
|
|
if (!Decl->isThisDeclarationADefinition())
|
|
return true;
|
|
|
|
if (!LocationChecker(Decl->getLocation()))
|
|
return true;
|
|
|
|
// Collect symbol information.
|
|
StringRef Name = Decl->getName();
|
|
StringRef USR = API.recordUSR(Decl);
|
|
PresumedLoc Loc =
|
|
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
|
|
DocComment Comment;
|
|
if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
|
|
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
|
|
Context.getDiagnostics());
|
|
|
|
// Build declaration fragments and sub-heading for the protocol.
|
|
DeclarationFragments Declaration =
|
|
DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(Decl);
|
|
DeclarationFragments SubHeading =
|
|
DeclarationFragmentsBuilder::getSubHeading(Decl);
|
|
|
|
ObjCProtocolRecord *ObjCProtocolRecord = API.addObjCProtocol(
|
|
Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration, SubHeading,
|
|
isInSystemHeader(Context, Decl));
|
|
|
|
recordObjCMethods(ObjCProtocolRecord, Decl->methods());
|
|
recordObjCProperties(ObjCProtocolRecord, Decl->properties());
|
|
recordObjCProtocols(ObjCProtocolRecord, Decl->protocols());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ExtractAPIVisitor::VisitTypedefNameDecl(const TypedefNameDecl *Decl) {
|
|
// Skip ObjC Type Parameter for now.
|
|
if (isa<ObjCTypeParamDecl>(Decl))
|
|
return true;
|
|
|
|
if (!Decl->isDefinedOutsideFunctionOrMethod())
|
|
return true;
|
|
|
|
if (!LocationChecker(Decl->getLocation()))
|
|
return true;
|
|
|
|
PresumedLoc Loc =
|
|
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
|
|
StringRef Name = Decl->getName();
|
|
StringRef USR = API.recordUSR(Decl);
|
|
DocComment Comment;
|
|
if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
|
|
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
|
|
Context.getDiagnostics());
|
|
|
|
QualType Type = Decl->getUnderlyingType();
|
|
SymbolReference SymRef =
|
|
TypedefUnderlyingTypeResolver(Context).getSymbolReferenceForType(Type,
|
|
API);
|
|
|
|
API.addTypedef(Name, USR, Loc, AvailabilitySet(Decl), Comment,
|
|
DeclarationFragmentsBuilder::getFragmentsForTypedef(Decl),
|
|
DeclarationFragmentsBuilder::getSubHeading(Decl), SymRef,
|
|
isInSystemHeader(Context, Decl));
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ExtractAPIVisitor::VisitObjCCategoryDecl(const ObjCCategoryDecl *Decl) {
|
|
// Collect symbol information.
|
|
StringRef Name = Decl->getName();
|
|
StringRef USR = API.recordUSR(Decl);
|
|
PresumedLoc Loc =
|
|
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
|
|
DocComment Comment;
|
|
if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
|
|
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
|
|
Context.getDiagnostics());
|
|
// Build declaration fragments and sub-heading for the category.
|
|
DeclarationFragments Declaration =
|
|
DeclarationFragmentsBuilder::getFragmentsForObjCCategory(Decl);
|
|
DeclarationFragments SubHeading =
|
|
DeclarationFragmentsBuilder::getSubHeading(Decl);
|
|
|
|
const ObjCInterfaceDecl *InterfaceDecl = Decl->getClassInterface();
|
|
SymbolReference Interface(InterfaceDecl->getName(),
|
|
API.recordUSR(InterfaceDecl));
|
|
|
|
ObjCCategoryRecord *ObjCCategoryRecord = API.addObjCCategory(
|
|
Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration, SubHeading,
|
|
Interface, isInSystemHeader(Context, Decl));
|
|
|
|
recordObjCMethods(ObjCCategoryRecord, Decl->methods());
|
|
recordObjCProperties(ObjCCategoryRecord, Decl->properties());
|
|
recordObjCInstanceVariables(ObjCCategoryRecord, Decl->ivars());
|
|
recordObjCProtocols(ObjCCategoryRecord, Decl->protocols());
|
|
|
|
return true;
|
|
}
|
|
|
|
/// Collect API information for the enum constants and associate with the
|
|
/// parent enum.
|
|
void ExtractAPIVisitor::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());
|
|
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, AvailabilitySet(Constant),
|
|
Comment, Declaration, SubHeading,
|
|
isInSystemHeader(Context, Constant));
|
|
}
|
|
}
|
|
|
|
/// Collect API information for the struct fields and associate with the
|
|
/// parent struct.
|
|
void ExtractAPIVisitor::recordStructFields(
|
|
StructRecord *StructRecord, const RecordDecl::field_range Fields) {
|
|
for (const auto *Field : Fields) {
|
|
// Collect symbol information.
|
|
StringRef Name = Field->getName();
|
|
StringRef USR = API.recordUSR(Field);
|
|
PresumedLoc Loc =
|
|
Context.getSourceManager().getPresumedLoc(Field->getLocation());
|
|
DocComment Comment;
|
|
if (auto *RawComment = Context.getRawCommentForDeclNoCache(Field))
|
|
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
|
|
Context.getDiagnostics());
|
|
|
|
// Build declaration fragments and sub-heading for the struct field.
|
|
DeclarationFragments Declaration =
|
|
DeclarationFragmentsBuilder::getFragmentsForField(Field);
|
|
DeclarationFragments SubHeading =
|
|
DeclarationFragmentsBuilder::getSubHeading(Field);
|
|
|
|
API.addStructField(StructRecord, Name, USR, Loc, AvailabilitySet(Field),
|
|
Comment, Declaration, SubHeading,
|
|
isInSystemHeader(Context, Field));
|
|
}
|
|
}
|
|
|
|
/// Collect API information for the Objective-C methods and associate with the
|
|
/// parent container.
|
|
void ExtractAPIVisitor::recordObjCMethods(
|
|
ObjCContainerRecord *Container,
|
|
const ObjCContainerDecl::method_range Methods) {
|
|
for (const auto *Method : Methods) {
|
|
// Don't record selectors for properties.
|
|
if (Method->isPropertyAccessor())
|
|
continue;
|
|
|
|
StringRef Name = API.copyString(Method->getSelector().getAsString());
|
|
StringRef USR = API.recordUSR(Method);
|
|
PresumedLoc Loc =
|
|
Context.getSourceManager().getPresumedLoc(Method->getLocation());
|
|
DocComment Comment;
|
|
if (auto *RawComment = Context.getRawCommentForDeclNoCache(Method))
|
|
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
|
|
Context.getDiagnostics());
|
|
|
|
// Build declaration fragments, sub-heading, and signature for the method.
|
|
DeclarationFragments Declaration =
|
|
DeclarationFragmentsBuilder::getFragmentsForObjCMethod(Method);
|
|
DeclarationFragments SubHeading =
|
|
DeclarationFragmentsBuilder::getSubHeading(Method);
|
|
FunctionSignature Signature =
|
|
DeclarationFragmentsBuilder::getFunctionSignature(Method);
|
|
|
|
API.addObjCMethod(Container, Name, USR, Loc, AvailabilitySet(Method),
|
|
Comment, Declaration, SubHeading, Signature,
|
|
Method->isInstanceMethod(),
|
|
isInSystemHeader(Context, Method));
|
|
}
|
|
}
|
|
|
|
void ExtractAPIVisitor::recordObjCProperties(
|
|
ObjCContainerRecord *Container,
|
|
const ObjCContainerDecl::prop_range Properties) {
|
|
for (const auto *Property : Properties) {
|
|
StringRef Name = Property->getName();
|
|
StringRef USR = API.recordUSR(Property);
|
|
PresumedLoc Loc =
|
|
Context.getSourceManager().getPresumedLoc(Property->getLocation());
|
|
DocComment Comment;
|
|
if (auto *RawComment = Context.getRawCommentForDeclNoCache(Property))
|
|
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
|
|
Context.getDiagnostics());
|
|
|
|
// Build declaration fragments and sub-heading for the property.
|
|
DeclarationFragments Declaration =
|
|
DeclarationFragmentsBuilder::getFragmentsForObjCProperty(Property);
|
|
DeclarationFragments SubHeading =
|
|
DeclarationFragmentsBuilder::getSubHeading(Property);
|
|
|
|
StringRef GetterName =
|
|
API.copyString(Property->getGetterName().getAsString());
|
|
StringRef SetterName =
|
|
API.copyString(Property->getSetterName().getAsString());
|
|
|
|
// Get the attributes for property.
|
|
unsigned Attributes = ObjCPropertyRecord::NoAttr;
|
|
if (Property->getPropertyAttributes() &
|
|
ObjCPropertyAttribute::kind_readonly)
|
|
Attributes |= ObjCPropertyRecord::ReadOnly;
|
|
|
|
API.addObjCProperty(
|
|
Container, Name, USR, Loc, AvailabilitySet(Property), Comment,
|
|
Declaration, SubHeading,
|
|
static_cast<ObjCPropertyRecord::AttributeKind>(Attributes), GetterName,
|
|
SetterName, Property->isOptional(),
|
|
!(Property->getPropertyAttributes() &
|
|
ObjCPropertyAttribute::kind_class),
|
|
isInSystemHeader(Context, Property));
|
|
}
|
|
}
|
|
|
|
void ExtractAPIVisitor::recordObjCInstanceVariables(
|
|
ObjCContainerRecord *Container,
|
|
const llvm::iterator_range<
|
|
DeclContext::specific_decl_iterator<ObjCIvarDecl>>
|
|
Ivars) {
|
|
for (const auto *Ivar : Ivars) {
|
|
StringRef Name = Ivar->getName();
|
|
StringRef USR = API.recordUSR(Ivar);
|
|
PresumedLoc Loc =
|
|
Context.getSourceManager().getPresumedLoc(Ivar->getLocation());
|
|
DocComment Comment;
|
|
if (auto *RawComment = Context.getRawCommentForDeclNoCache(Ivar))
|
|
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
|
|
Context.getDiagnostics());
|
|
|
|
// Build declaration fragments and sub-heading for the instance variable.
|
|
DeclarationFragments Declaration =
|
|
DeclarationFragmentsBuilder::getFragmentsForField(Ivar);
|
|
DeclarationFragments SubHeading =
|
|
DeclarationFragmentsBuilder::getSubHeading(Ivar);
|
|
|
|
ObjCInstanceVariableRecord::AccessControl Access =
|
|
Ivar->getCanonicalAccessControl();
|
|
|
|
API.addObjCInstanceVariable(
|
|
Container, Name, USR, Loc, AvailabilitySet(Ivar), Comment, Declaration,
|
|
SubHeading, Access, isInSystemHeader(Context, Ivar));
|
|
}
|
|
}
|
|
|
|
void ExtractAPIVisitor::recordObjCProtocols(
|
|
ObjCContainerRecord *Container,
|
|
ObjCInterfaceDecl::protocol_range Protocols) {
|
|
for (const auto *Protocol : Protocols)
|
|
Container->Protocols.emplace_back(Protocol->getName(),
|
|
API.recordUSR(Protocol));
|
|
}
|