diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2023-04-14 21:41:27 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2023-06-22 18:20:56 +0000 |
| commit | bdd1243df58e60e85101c09001d9812a789b6bc4 (patch) | |
| tree | a1ce621c7301dd47ba2ddc3b8eaa63b441389481 /contrib/llvm-project/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp | |
| parent | 781624ca2d054430052c828ba8d2c2eaf2d733e7 (diff) | |
| parent | e3b557809604d036af6e00c60f012c2025b59a5e (diff) | |
Diffstat (limited to 'contrib/llvm-project/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp')
| -rw-r--r-- | contrib/llvm-project/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp | 612 |
1 files changed, 36 insertions, 576 deletions
diff --git a/contrib/llvm-project/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/contrib/llvm-project/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp index 1a785182e363..644845efb819 100644 --- a/contrib/llvm-project/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp +++ b/contrib/llvm-project/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp @@ -7,25 +7,20 @@ //===----------------------------------------------------------------------===// /// /// \file -/// This file implements the ExtractAPIAction, and ASTVisitor/Consumer to -/// collect API information. +/// This file implements the ExtractAPIAction, and ASTConsumer to collect API +/// information. /// //===----------------------------------------------------------------------===// -#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/AST/RecursiveASTVisitor.h" +#include "clang/Basic/DiagnosticFrontend.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/ExtractAPI/APIIgnoresList.h" +#include "clang/ExtractAPI/ExtractAPIVisitor.h" #include "clang/ExtractAPI/FrontendActions.h" #include "clang/ExtractAPI/Serialization/SymbolGraphSerializer.h" #include "clang/Frontend/ASTConsumers.h" @@ -38,12 +33,14 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/Regex.h" #include "llvm/Support/raw_ostream.h" #include <memory> +#include <optional> #include <utility> using namespace clang; @@ -51,16 +48,9 @@ using namespace extractapi; namespace { -StringRef getTypedefName(const TagDecl *Decl) { - if (const auto *TypedefDecl = Decl->getTypedefNameForAnonDecl()) - return TypedefDecl->getName(); - - return {}; -} - -Optional<std::string> getRelativeIncludeName(const CompilerInstance &CI, - StringRef File, - bool *IsQuoted = nullptr) { +std::optional<std::string> getRelativeIncludeName(const CompilerInstance &CI, + StringRef File, + bool *IsQuoted = nullptr) { assert(CI.hasFileManager() && "CompilerInstance does not have a FileNamager!"); @@ -154,7 +144,7 @@ Optional<std::string> getRelativeIncludeName(const CompilerInstance &CI, Rule.match(File, &Matches); // Returned matches are always in stable order. if (Matches.size() != 4) - return None; + return std::nullopt; return path::convert_to_slash( (Matches[1].drop_front(Matches[1].rfind('/') + 1) + "/" + @@ -169,11 +159,11 @@ Optional<std::string> getRelativeIncludeName(const CompilerInstance &CI, } // Couldn't determine a include name, use full path instead. - return None; + return std::nullopt; } struct LocationFileChecker { - bool isLocationInKnownFile(SourceLocation Loc) { + bool operator()(SourceLocation Loc) { // If the loc refers to a macro expansion we need to first get the file // location of the expansion. auto &SM = CI.getSourceManager(); @@ -229,554 +219,6 @@ private: llvm::DenseSet<const FileEntry *> ExternalFileEntries; }; -/// The RecursiveASTVisitor to traverse symbol declarations and collect API -/// information. -class ExtractAPIVisitor : public RecursiveASTVisitor<ExtractAPIVisitor> { -public: - ExtractAPIVisitor(ASTContext &Context, LocationFileChecker &LCF, APISet &API) - : Context(Context), API(API), LCF(LCF) {} - - const APISet &getAPI() const { return API; } - - bool 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 (!LCF.isLocationInKnownFile(Decl->getLocation())) - 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); - 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, Availability, Linkage, Comment, - Declaration, SubHeading); - return true; - } - - bool 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 (!LCF.isLocationInKnownFile(Decl->getLocation())) - 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); - 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, Availability, Linkage, Comment, - Declaration, SubHeading, Signature); - return true; - } - - bool VisitEnumDecl(const EnumDecl *Decl) { - if (!Decl->isComplete()) - return true; - - // Skip forward declaration. - if (!Decl->isThisDeclarationADefinition()) - return true; - - if (!LCF.isLocationInKnownFile(Decl->getLocation())) - return true; - - // Collect symbol information. - 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()); - 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(API.copyString(Name), USR, Loc, Availability, Comment, - Declaration, SubHeading); - - // Now collect information about the enumerators in this enum. - recordEnumConstants(EnumRecord, Decl->enumerators()); - - return true; - } - - bool 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 (!LCF.isLocationInKnownFile(Decl->getLocation())) - return true; - - // Collect symbol information. - StringRef Name = Decl->getName(); - if (Name.empty()) - Name = getTypedefName(Decl); - 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 struct. - DeclarationFragments Declaration = - DeclarationFragmentsBuilder::getFragmentsForStruct(Decl); - DeclarationFragments SubHeading = - DeclarationFragmentsBuilder::getSubHeading(Decl); - - StructRecord *StructRecord = API.addStruct( - Name, USR, Loc, Availability, Comment, Declaration, SubHeading); - - // Now collect information about the fields in this struct. - recordStructFields(StructRecord, Decl->fields()); - - return true; - } - - bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *Decl) { - // Skip forward declaration for classes (@class) - if (!Decl->isThisDeclarationADefinition()) - return true; - - if (!LCF.isLocationInKnownFile(Decl->getLocation())) - 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); - 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, Availability, Linkage, Comment, - Declaration, SubHeading, SuperClass); - - // 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 VisitObjCProtocolDecl(const ObjCProtocolDecl *Decl) { - // Skip forward declaration for protocols (@protocol). - if (!Decl->isThisDeclarationADefinition()) - return true; - - if (!LCF.isLocationInKnownFile(Decl->getLocation())) - 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 protocol. - DeclarationFragments Declaration = - DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(Decl); - DeclarationFragments SubHeading = - DeclarationFragmentsBuilder::getSubHeading(Decl); - - ObjCProtocolRecord *ObjCProtocolRecord = API.addObjCProtocol( - Name, USR, Loc, Availability, Comment, Declaration, SubHeading); - - recordObjCMethods(ObjCProtocolRecord, Decl->methods()); - recordObjCProperties(ObjCProtocolRecord, Decl->properties()); - recordObjCProtocols(ObjCProtocolRecord, Decl->protocols()); - - return true; - } - - bool VisitTypedefNameDecl(const TypedefNameDecl *Decl) { - // Skip ObjC Type Parameter for now. - if (isa<ObjCTypeParamDecl>(Decl)) - return true; - - if (!Decl->isDefinedOutsideFunctionOrMethod()) - return true; - - if (!LCF.isLocationInKnownFile(Decl->getLocation())) - return true; - - PresumedLoc Loc = - Context.getSourceManager().getPresumedLoc(Decl->getLocation()); - StringRef Name = Decl->getName(); - AvailabilityInfo Availability = getAvailability(Decl); - 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, Availability, Comment, - DeclarationFragmentsBuilder::getFragmentsForTypedef(Decl), - DeclarationFragmentsBuilder::getSubHeading(Decl), SymRef); - - return true; - } - - bool VisitObjCCategoryDecl(const ObjCCategoryDecl *Decl) { - // 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 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, Availability, Comment, Declaration, - SubHeading, Interface); - - recordObjCMethods(ObjCCategoryRecord, Decl->methods()); - recordObjCProperties(ObjCCategoryRecord, Decl->properties()); - recordObjCInstanceVariables(ObjCCategoryRecord, Decl->ivars()); - recordObjCProtocols(ObjCCategoryRecord, Decl->protocols()); - - return true; - } - -private: - /// Get availability information of the declaration \p D. - AvailabilityInfo getAvailability(const Decl *D) const { - StringRef PlatformName = Context.getTargetInfo().getPlatformName(); - - AvailabilityInfo Availability; - // Collect availability attributes from all redeclarations. - for (const auto *RD : D->redecls()) { - for (const auto *A : RD->specific_attrs<AvailabilityAttr>()) { - if (A->getPlatform()->getName() != PlatformName) - continue; - Availability = AvailabilityInfo(A->getIntroduced(), A->getDeprecated(), - A->getObsoleted(), A->getUnavailable(), - /* UnconditionallyDeprecated */ false, - /* UnconditionallyUnavailable */ false); - break; - } - - if (const auto *A = RD->getAttr<UnavailableAttr>()) - if (!A->isImplicit()) { - Availability.Unavailable = true; - Availability.UnconditionallyUnavailable = true; - } - - if (const auto *A = RD->getAttr<DeprecatedAttr>()) - if (!A->isImplicit()) - Availability.UnconditionallyDeprecated = true; - } - - 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); - } - } - - /// Collect API information for the struct fields and associate with the - /// parent struct. - void 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()); - AvailabilityInfo Availability = getAvailability(Field); - 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, Availability, Comment, - Declaration, SubHeading); - } - } - - /// Collect API information for the Objective-C methods and associate with the - /// parent container. - void 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()); - AvailabilityInfo Availability = getAvailability(Method); - 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, Availability, Comment, - Declaration, SubHeading, Signature, - Method->isInstanceMethod()); - } - } - - void 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()); - AvailabilityInfo Availability = getAvailability(Property); - 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; - if (Property->getPropertyAttributes() & ObjCPropertyAttribute::kind_class) - Attributes |= ObjCPropertyRecord::Class; - - API.addObjCProperty( - Container, Name, USR, Loc, Availability, Comment, Declaration, - SubHeading, - static_cast<ObjCPropertyRecord::AttributeKind>(Attributes), - GetterName, SetterName, Property->isOptional()); - } - } - - void 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()); - AvailabilityInfo Availability = getAvailability(Ivar); - 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, Availability, - Comment, Declaration, SubHeading, Access); - } - } - - void recordObjCProtocols(ObjCContainerRecord *Container, - ObjCInterfaceDecl::protocol_range Protocols) { - for (const auto *Protocol : Protocols) - Container->Protocols.emplace_back(Protocol->getName(), - API.recordUSR(Protocol)); - } - - ASTContext &Context; - APISet &API; - LocationFileChecker &LCF; -}; - class ExtractAPIConsumer : public ASTConsumer { public: ExtractAPIConsumer(ASTContext &Context, @@ -837,7 +279,7 @@ public: if (PM.MD->getMacroInfo()->isUsedForHeaderGuard()) continue; - if (!LCF.isLocationInKnownFile(PM.MacroNameToken.getLocation())) + if (!LCF(PM.MacroNameToken.getLocation())) continue; StringRef Name = PM.MacroNameToken.getIdentifierInfo()->getName(); @@ -848,7 +290,8 @@ public: API.addMacroDefinition( Name, USR, Loc, DeclarationFragmentsBuilder::getFragmentsForMacro(Name, PM.MD), - DeclarationFragmentsBuilder::getSubHeadingForMacro(Name)); + DeclarationFragmentsBuilder::getSubHeadingForMacro(Name), + SM.isInSystemHeader(PM.MacroNameToken.getLocation())); } PendingMacros.clear(); @@ -878,19 +321,36 @@ ExtractAPIAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { if (!OS) return nullptr; - ProductName = CI.getFrontendOpts().ProductName; + auto ProductName = CI.getFrontendOpts().ProductName; // Now that we have enough information about the language options and the // target triple, let's create the APISet before anyone uses it. API = std::make_unique<APISet>( CI.getTarget().getTriple(), - CI.getFrontendOpts().Inputs.back().getKind().getLanguage()); + CI.getFrontendOpts().Inputs.back().getKind().getLanguage(), ProductName); auto LCF = std::make_unique<LocationFileChecker>(CI, KnownInputFiles); CI.getPreprocessor().addPPCallbacks(std::make_unique<MacroCallback>( CI.getSourceManager(), *LCF, *API, CI.getPreprocessor())); + // Do not include location in anonymous decls. + PrintingPolicy Policy = CI.getASTContext().getPrintingPolicy(); + Policy.AnonymousTagLocations = false; + CI.getASTContext().setPrintingPolicy(Policy); + + if (!CI.getFrontendOpts().ExtractAPIIgnoresFile.empty()) { + llvm::handleAllErrors( + APIIgnoresList::create(CI.getFrontendOpts().ExtractAPIIgnoresFile, + CI.getFileManager()) + .moveInto(IgnoresList), + [&CI](const IgnoresFileNotFound &Err) { + CI.getDiagnostics().Report( + diag::err_extract_api_ignores_file_not_found) + << Err.Path; + }); + } + return std::make_unique<ExtractAPIConsumer>(CI.getASTContext(), std::move(LCF), *API); } @@ -959,7 +419,7 @@ void ExtractAPIAction::EndSourceFileAction() { // Setup a SymbolGraphSerializer to write out collected API information in // the Symbol Graph format. // FIXME: Make the kind of APISerializer configurable. - SymbolGraphSerializer SGSerializer(*API, ProductName); + SymbolGraphSerializer SGSerializer(*API, IgnoresList); SGSerializer.serialize(*OS); OS.reset(); } |
