From 158a431227a876306fe5838936413dd51588d0c6 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Mon, 27 Mar 2023 22:12:11 +0100 Subject: [PATCH] Revert ExtractAPI from https://reviews.llvm.org/D146656 --- clang/include/clang/ExtractAPI/ExtractAPIVisitor.h | 604 +-------------------- clang/lib/ExtractAPI/CMakeLists.txt | 1 + clang/lib/ExtractAPI/DeclarationFragments.cpp | 2 +- clang/lib/ExtractAPI/ExtractAPIConsumer.cpp | 30 +- clang/lib/ExtractAPI/ExtractAPIVisitor.cpp | 560 +++++++++++++++++++ .../ExtractAPI/TypedefUnderlyingTypeResolver.cpp | 2 +- .../ExtractAPI/TypedefUnderlyingTypeResolver.h | 0 clang/test/Index/extract-api-cursor.m | 177 +++--- clang/tools/c-index-test/c-index-test.c | 20 - clang/tools/libclang/CXExtractAPI.cpp | 132 ++--- 10 files changed, 696 insertions(+), 832 deletions(-) create mode 100644 clang/lib/ExtractAPI/ExtractAPIVisitor.cpp rename clang/{include/clang => lib}/ExtractAPI/TypedefUnderlyingTypeResolver.h (100%) diff --git a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h index a31648b..f6546fb 100644 --- a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h +++ b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h @@ -14,27 +14,24 @@ #ifndef LLVM_CLANG_EXTRACTAPI_EXTRACT_API_VISITOR_H #define LLVM_CLANG_EXTRACTAPI_EXTRACT_API_VISITOR_H -#include "llvm/ADT/FunctionExtras.h" - -#include "clang/AST/ASTContext.h" -#include "clang/AST/ParentMapContext.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/SourceManager.h" #include "clang/ExtractAPI/API.h" -#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h" -#include +#include "llvm/ADT/FunctionExtras.h" namespace clang { namespace extractapi { -namespace impl { - -template -class ExtractAPIVisitorBase : public RecursiveASTVisitor { -protected: - ExtractAPIVisitorBase(ASTContext &Context, APISet &API) - : Context(Context), API(API) {} +/// The RecursiveASTVisitor to traverse symbol declarations and collect API +/// information. +class ExtractAPIVisitor : public RecursiveASTVisitor { public: + ExtractAPIVisitor(ASTContext &Context, + llvm::unique_function LocationChecker, + APISet &API) + : Context(Context), API(API), + LocationChecker(std::move(LocationChecker)) {} + const APISet &getAPI() const { return API; } bool VisitVarDecl(const VarDecl *Decl); @@ -53,11 +50,7 @@ public: bool VisitObjCCategoryDecl(const ObjCCategoryDecl *Decl); - bool shouldDeclBeIncluded(const Decl *Decl) const; - - const RawComment *fetchRawCommentForDecl(const Decl *Decl) const; - -protected: +private: /// Collect API information for the enum constants and associate with the /// parent enum. void recordEnumConstants(EnumRecord *EnumRecord, @@ -84,582 +77,9 @@ protected: void recordObjCProtocols(ObjCContainerRecord *Container, ObjCInterfaceDecl::protocol_range Protocols); - ASTContext &Context; APISet &API; - - StringRef getTypedefName(const TagDecl *Decl) { - if (const auto *TypedefDecl = Decl->getTypedefNameForAnonDecl()) - return TypedefDecl->getName(); - - return {}; - } - - bool isInSystemHeader(const Decl *D) { - return Context.getSourceManager().isInSystemHeader(D->getLocation()); - } - -private: - Derived &getDerivedExtractAPIVisitor() { - return *static_cast(this); - } -}; - -template -bool ExtractAPIVisitorBase::VisitVarDecl(const VarDecl *Decl) { - // skip function parameters. - if (isa(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 (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) - 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 = - getDerivedExtractAPIVisitor().fetchRawCommentForDecl(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(Decl)); - return true; -} - -template -bool ExtractAPIVisitorBase::VisitFunctionDecl( - const FunctionDecl *Decl) { - if (const auto *Method = dyn_cast(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.template get()) - return true; - } - - // Skip ConstructorDecl and DestructorDecl. - if (isa(Method) || isa(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 (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) - 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 = - getDerivedExtractAPIVisitor().fetchRawCommentForDecl(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(Decl)); - return true; -} - -template -bool ExtractAPIVisitorBase::VisitEnumDecl(const EnumDecl *Decl) { - if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) - 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 = - getDerivedExtractAPIVisitor().fetchRawCommentForDecl(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(Decl)); - - // Now collect information about the enumerators in this enum. - getDerivedExtractAPIVisitor().recordEnumConstants(EnumRecord, - Decl->enumerators()); - - return true; -} - -template -bool ExtractAPIVisitorBase::VisitRecordDecl(const RecordDecl *Decl) { - // Skip C++ structs/classes/unions - // TODO: support C++ records - if (isa(Decl)) - return true; - - if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) - 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 = - getDerivedExtractAPIVisitor().fetchRawCommentForDecl(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(Decl)); - - // Now collect information about the fields in this struct. - getDerivedExtractAPIVisitor().recordStructFields(StructRecord, - Decl->fields()); - - return true; -} - -template -bool ExtractAPIVisitorBase::VisitObjCInterfaceDecl( - const ObjCInterfaceDecl *Decl) { - if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) - 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 = - getDerivedExtractAPIVisitor().fetchRawCommentForDecl(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(Decl)); - - // Record all methods (selectors). This doesn't include automatically - // synthesized property methods. - getDerivedExtractAPIVisitor().recordObjCMethods(ObjCInterfaceRecord, - Decl->methods()); - getDerivedExtractAPIVisitor().recordObjCProperties(ObjCInterfaceRecord, - Decl->properties()); - getDerivedExtractAPIVisitor().recordObjCInstanceVariables(ObjCInterfaceRecord, - Decl->ivars()); - getDerivedExtractAPIVisitor().recordObjCProtocols(ObjCInterfaceRecord, - Decl->protocols()); - - return true; -} - -template -bool ExtractAPIVisitorBase::VisitObjCProtocolDecl( - const ObjCProtocolDecl *Decl) { - if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) - 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 = - getDerivedExtractAPIVisitor().fetchRawCommentForDecl(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(Decl)); - - getDerivedExtractAPIVisitor().recordObjCMethods(ObjCProtocolRecord, - Decl->methods()); - getDerivedExtractAPIVisitor().recordObjCProperties(ObjCProtocolRecord, - Decl->properties()); - getDerivedExtractAPIVisitor().recordObjCProtocols(ObjCProtocolRecord, - Decl->protocols()); - - return true; -} - -template -bool ExtractAPIVisitorBase::VisitTypedefNameDecl( - const TypedefNameDecl *Decl) { - // Skip ObjC Type Parameter for now. - if (isa(Decl)) - return true; - - if (!Decl->isDefinedOutsideFunctionOrMethod()) - return true; - - if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) - return true; - - PresumedLoc Loc = - Context.getSourceManager().getPresumedLoc(Decl->getLocation()); - StringRef Name = Decl->getName(); - StringRef USR = API.recordUSR(Decl); - DocComment Comment; - if (auto *RawComment = - getDerivedExtractAPIVisitor().fetchRawCommentForDecl(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(Decl)); - - return true; -} - -template -bool ExtractAPIVisitorBase::VisitObjCCategoryDecl( - const ObjCCategoryDecl *Decl) { - if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) - return true; - - StringRef Name = Decl->getName(); - StringRef USR = API.recordUSR(Decl); - PresumedLoc Loc = - Context.getSourceManager().getPresumedLoc(Decl->getLocation()); - DocComment Comment; - if (auto *RawComment = - getDerivedExtractAPIVisitor().fetchRawCommentForDecl(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(Decl)); - - getDerivedExtractAPIVisitor().recordObjCMethods(ObjCCategoryRecord, - Decl->methods()); - getDerivedExtractAPIVisitor().recordObjCProperties(ObjCCategoryRecord, - Decl->properties()); - getDerivedExtractAPIVisitor().recordObjCInstanceVariables(ObjCCategoryRecord, - Decl->ivars()); - getDerivedExtractAPIVisitor().recordObjCProtocols(ObjCCategoryRecord, - Decl->protocols()); - - return true; -} - -/// Collect API information for the enum constants and associate with the -/// parent enum. -template -void ExtractAPIVisitorBase::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 = - getDerivedExtractAPIVisitor().fetchRawCommentForDecl(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(Constant)); - } -} - -/// Collect API information for the struct fields and associate with the -/// parent struct. -template -void ExtractAPIVisitorBase::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 = - getDerivedExtractAPIVisitor().fetchRawCommentForDecl(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(Field)); - } -} - -/// Collect API information for the Objective-C methods and associate with the -/// parent container. -template -void ExtractAPIVisitorBase::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 = - getDerivedExtractAPIVisitor().fetchRawCommentForDecl(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(Method)); - } -} - -template -void ExtractAPIVisitorBase::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 = - getDerivedExtractAPIVisitor().fetchRawCommentForDecl(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(Attributes), GetterName, - SetterName, Property->isOptional(), - !(Property->getPropertyAttributes() & - ObjCPropertyAttribute::kind_class), - isInSystemHeader(Property)); - } -} - -template -void ExtractAPIVisitorBase::recordObjCInstanceVariables( - ObjCContainerRecord *Container, - const llvm::iterator_range< - DeclContext::specific_decl_iterator> - 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 = - getDerivedExtractAPIVisitor().fetchRawCommentForDecl(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(Ivar)); - } -} - -template -void ExtractAPIVisitorBase::recordObjCProtocols( - ObjCContainerRecord *Container, - ObjCInterfaceDecl::protocol_range Protocols) { - for (const auto *Protocol : Protocols) - Container->Protocols.emplace_back(Protocol->getName(), - API.recordUSR(Protocol)); -} - -} // namespace impl - -/// The RecursiveASTVisitor to traverse symbol declarations and collect API -/// information. -template -class ExtractAPIVisitor - : public impl::ExtractAPIVisitorBase, ExtractAPIVisitor<>, Derived>> { - using Base = impl::ExtractAPIVisitorBase, ExtractAPIVisitor<>, Derived>>; - -public: - ExtractAPIVisitor(ASTContext &Context, APISet &API) : Base(Context, API) {} - - bool shouldDeclBeIncluded(const Decl *D) const { return true; } - const RawComment *fetchRawCommentForDecl(const Decl *D) const { - return this->Context.getRawCommentForDeclNoCache(D); - } + llvm::unique_function LocationChecker; }; } // namespace extractapi diff --git a/clang/lib/ExtractAPI/CMakeLists.txt b/clang/lib/ExtractAPI/CMakeLists.txt index 153d4b9..80fafcd 100644 --- a/clang/lib/ExtractAPI/CMakeLists.txt +++ b/clang/lib/ExtractAPI/CMakeLists.txt @@ -8,6 +8,7 @@ add_clang_library(clangExtractAPI APIIgnoresList.cpp AvailabilityInfo.cpp ExtractAPIConsumer.cpp + ExtractAPIVisitor.cpp DeclarationFragments.cpp Serialization/SerializerBase.cpp Serialization/SymbolGraphSerializer.cpp diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index 675d4e8..c42a1de 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/ExtractAPI/DeclarationFragments.h" -#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h" +#include "TypedefUnderlyingTypeResolver.h" #include "clang/Index/USRGeneration.h" #include "llvm/ADT/StringSwitch.h" diff --git a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp index c27b2d0..c1e47b1 100644 --- a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp +++ b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp @@ -12,10 +12,8 @@ /// //===----------------------------------------------------------------------===// -#include "clang/AST/ASTConcept.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/DeclObjC.h" #include "clang/Basic/DiagnosticFrontend.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" @@ -35,7 +33,6 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" @@ -222,34 +219,11 @@ private: llvm::DenseSet ExternalFileEntries; }; -struct BatchExtractAPIVisitor : ExtractAPIVisitor { - bool shouldDeclBeIncluded(const Decl *D) const { - bool ShouldBeIncluded = true; - // Check that we have the definition for redeclarable types. - if (auto *TD = llvm::dyn_cast(D)) - ShouldBeIncluded = TD->isThisDeclarationADefinition(); - else if (auto *Interface = llvm::dyn_cast(D)) - ShouldBeIncluded = Interface->isThisDeclarationADefinition(); - else if (auto *Protocol = llvm::dyn_cast(D)) - ShouldBeIncluded = Protocol->isThisDeclarationADefinition(); - - ShouldBeIncluded = ShouldBeIncluded && LCF(D->getLocation()); - return ShouldBeIncluded; - } - - BatchExtractAPIVisitor(LocationFileChecker &LCF, ASTContext &Context, - APISet &API) - : ExtractAPIVisitor(Context, API), LCF(LCF) {} - -private: - LocationFileChecker &LCF; -}; - class ExtractAPIConsumer : public ASTConsumer { public: ExtractAPIConsumer(ASTContext &Context, std::unique_ptr LCF, APISet &API) - : Visitor(*LCF, Context, API), LCF(std::move(LCF)) {} + : Visitor(Context, *LCF, API), LCF(std::move(LCF)) {} void HandleTranslationUnit(ASTContext &Context) override { // Use ExtractAPIVisitor to traverse symbol declarations in the context. @@ -257,7 +231,7 @@ public: } private: - BatchExtractAPIVisitor Visitor; + ExtractAPIVisitor Visitor; std::unique_ptr LCF; }; diff --git a/clang/lib/ExtractAPI/ExtractAPIVisitor.cpp b/clang/lib/ExtractAPI/ExtractAPIVisitor.cpp new file mode 100644 index 0000000..24260cf --- /dev/null +++ b/clang/lib/ExtractAPI/ExtractAPIVisitor.cpp @@ -0,0 +1,560 @@ +//===- 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 +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(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(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()) + return true; + } + + // Skip ConstructorDecl and DestructorDecl. + if (isa(Method) || isa(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(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(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(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> + 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)); +} diff --git a/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp b/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp index 3a5f62c..3da2424 100644 --- a/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp +++ b/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp @@ -11,7 +11,7 @@ /// //===----------------------------------------------------------------------===// -#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h" +#include "TypedefUnderlyingTypeResolver.h" #include "clang/Index/USRGeneration.h" using namespace clang; diff --git a/clang/include/clang/ExtractAPI/TypedefUnderlyingTypeResolver.h b/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.h similarity index 100% rename from clang/include/clang/ExtractAPI/TypedefUnderlyingTypeResolver.h rename to clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.h diff --git a/clang/test/Index/extract-api-cursor.m b/clang/test/Index/extract-api-cursor.m index 16844ca..078f2f5 100644 --- a/clang/test/Index/extract-api-cursor.m +++ b/clang/test/Index/extract-api-cursor.m @@ -1,5 +1,3 @@ -// Test is line- and column-sensitive. Run lines are below - /// Foo docs struct Foo { /// Bar docs @@ -27,94 +25,91 @@ struct Foo { - (void)derivedMethodWithValue:(id)value; @end -@implementation Derived -- (void)derivedMethodWithValue:(id)value { - int a = 5; -} +/// This won't show up in docs because we can't serialize it +@interface Derived () +/// Derived method in category docs, won't show up either. +- (void)derivedMethodInCategory; @end -// RUN: c-index-test -single-symbol-sgf-at=%s:4:9 local %s | FileCheck -check-prefix=CHECK-FOO %s -// CHECK-FOO: "parentContexts":[] -// CHECK-FOO: "relatedSymbols":[] -// CHECK-FOO: "relationships":[] -// CHECK-FOO: "text":"Foo docs" -// CHECK-FOO: "kind":{"displayName":"Structure","identifier":"objective-c.struct"} -// CHECK-FOO: "title":"Foo" - -// RUN: c-index-test -single-symbol-sgf-at=%s:6:9 local %s | FileCheck -check-prefix=CHECK-BAR %s -// CHECK-BAR: "parentContexts":[{"kind":"objective-c.struct","name":"Foo","usr":"c:@S@Foo"}] -// CHECK-BAR: "relatedSymbols":[] -// CHECK-BAR: "relationships":[{"kind":"memberOf","source":"c:@S@Foo@FI@bar","target":"c:@S@Foo" -// CHECK-BAR: "text":"Bar docs" -// CHECK-BAR: "kind":{"displayName":"Instance Property","identifier":"objective-c.property"} -// CHECK-BAR: "title":"bar" - -// RUN: c-index-test -single-symbol-sgf-at=%s:10:11 local %s | FileCheck -check-prefix=CHECK-BASE %s -// CHECK-BASE: "parentContexts":[] -// CHECK-BASE: "relatedSymbols":[] -// CHECK-BASE: "relationships":[] -// CHECK-BASE: "text":"Base docs" -// CHECK-BASE: "kind":{"displayName":"Class","identifier":"objective-c.class"} -// CHECK-BASE: "title":"Base" - -// RUN: c-index-test -single-symbol-sgf-at=%s:12:25 local %s | FileCheck -check-prefix=CHECK-BASE-PROP %s -// CHECK-BASE-PROP: "parentContexts":[{"kind":"objective-c.class","name":"Base","usr":"c:objc(cs)Base"}] -// CHECK-BASE-PROP: "relatedSymbols":[{"accessLevel":"public","declarationLanguage":"objective-c" -// CHECK-BASE-PROP: "isSystem":false -// CHECK-BASE-PROP: "usr":"c:@S@Foo"}] -// CHECK-BASE-PROP: "relationships":[{"kind":"memberOf","source":"c:objc(cs)Base(py)baseProperty","target":"c:objc(cs)Base" -// CHECK-BASE-PROP: "text":"Base property docs" -// CHECK-BASE-PROP: "kind":{"displayName":"Instance Property","identifier":"objective-c.property"} -// CHECK-BASE-PROP: "title":"baseProperty" - -// RUN: c-index-test -single-symbol-sgf-at=%s:15:9 local %s | FileCheck -check-prefix=CHECK-BASE-METHOD %s -// CHECK-BASE-METHOD: "parentContexts":[{"kind":"objective-c.class","name":"Base","usr":"c:objc(cs)Base"}] -// CHECK-BASE-METHOD: "relatedSymbols":[] -// CHECK-BASE-METHOD: "relationships":[{"kind":"memberOf","source":"c:objc(cs)Base(im)baseMethodWithArg:","target":"c:objc(cs)Base" -// CHECK-BASE-METHOD: "text":"Base method docs" -// CHECK-BASE-METHOD: "kind":{"displayName":"Instance Method","identifier":"objective-c.method"} -// CHECK-BASE-METHOD: "title":"baseMethodWithArg:" - -// RUN: c-index-test -single-symbol-sgf-at=%s:19:11 local %s | FileCheck -check-prefix=CHECK-PROTOCOL %s -// CHECK-PROTOCOL: "parentContexts":[] -// CHECK-PROTOCOL: "relatedSymbols":[] -// CHECK-PROTOCOL: "relationships":[] -// CHECK-PROTOCOL: "text":"Protocol docs" -// CHECK-PROTOCOL: "kind":{"displayName":"Protocol","identifier":"objective-c.protocol"} -// CHECK-PROTOCOL: "title":"Protocol" - -// RUN: c-index-test -single-symbol-sgf-at=%s:21:27 local %s | FileCheck -check-prefix=CHECK-PROTOCOL-PROP %s -// CHECK-PROTOCOL-PROP: "parentContexts":[{"kind":"objective-c.protocol","name":"Protocol","usr":"c:objc(pl)Protocol"}] -// CHECK-PROTOCOL-PROP: "relatedSymbols":[{"accessLevel":"public","declarationLanguage":"objective-c" -// CHECK-PROTOCOL-PROP: "isSystem":false -// CHECK-PROTOCOL-PROP: "usr":"c:@S@Foo"}] -// CHECK-PROTOCOL-PROP: "relationships":[{"kind":"memberOf","source":"c:objc(pl)Protocol(py)protocolProperty","target":"c:objc(pl)Protocol" -// CHECK-PROTOCOL-PROP: "text":"Protocol property docs" -// CHECK-PROTOCOL-PROP: "kind":{"displayName":"Instance Property","identifier":"objective-c.property"} -// CHECK-PROTOCOL-PROP: "title":"protocolProperty" - -// RUN: c-index-test -single-symbol-sgf-at=%s:25:15 local %s | FileCheck -check-prefix=CHECK-DERIVED %s -// CHECK-DERIVED: "parentContexts":[] -// CHECK-DERIVED: "relatedSymbols":[{"accessLevel":"public","declarationLanguage":"objective-c" -// CHECK-DERIVED: "isSystem":false -// CHECK-DERIVED: "usr":"c:objc(cs)Base"}] -// CHECK-DERIVED: "relationships":[{"kind":"inheritsFrom","source":"c:objc(cs)Derived","target":"c:objc(cs)Base" -// CHECK-DERIVED: "text":"Derived docs" -// CHECK-DERIVED: "kind":{"displayName":"Class","identifier":"objective-c.class"} -// CHECK-DERIVED: "title":"Derived" - -// RUN: c-index-test -single-symbol-sgf-at=%s:27:11 local %s | FileCheck -check-prefix=CHECK-DERIVED-METHOD %s -// CHECK-DERIVED-METHOD: "parentContexts":[{"kind":"objective-c.class","name":"Derived","usr":"c:objc(cs)Derived"}] -// CHECK-DERIVED-METHOD: "relatedSymbols":[] -// CHECK-DERIVED-METHOD: "relationships":[{"kind":"memberOf","source":"c:objc(cs)Derived(im)derivedMethodWithValue:","target":"c:objc(cs)Derived" -// CHECK-DERIVED-METHOD: "text":"Derived method docs" -// CHECK-DERIVED-METHOD: "kind":{"displayName":"Instance Method","identifier":"objective-c.method"} -// CHECK-DERIVED-METHOD: "title":"derivedMethodWithValue:" - -// RUN: c-index-test -single-symbol-sgf-at=%s:31:11 local %s | FileCheck -check-prefix=CHECK-DERIVED-METHOD-IMPL %s -// CHECK-DERIVED-METHOD-IMPL: "parentContexts":[{"kind":"objective-c.class","name":"Derived","usr":"c:objc(cs)Derived"}] -// CHECK-DERIVED-METHOD-IMPL: "relatedSymbols":[] -// CHECK-DERIVED-METHOD-IMPL: "relationships":[{"kind":"memberOf","source":"c:objc(cs)Derived(im)derivedMethodWithValue:","target":"c:objc(cs)Derived" -// CHECK-DERIVED-METHOD-IMPL: "text":"Derived method docs" -// CHECK-DERIVED-METHOD-IMPL: "kind":{"displayName":"Instance Method","identifier":"objective-c.method"} -// CHECK-DERIVED-METHOD-IMPL: "title":"derivedMethodWithValue:" +// RUN: c-index-test -single-symbol-sgfs local %s | FileCheck %s + +// Checking for Foo +// CHECK: "parentContexts":[] +// CHECK-SAME: "relatedSymbols":[] +// CHECK-SAME: "relationships":[] +// CHECK-SAME: "text":"Foo docs" +// CHECK-SAME: "kind":{"displayName":"Structure","identifier":"objective-c.struct"} +// CHECK-SAME: "title":"Foo" + +// Checking for bar +// CHECK-NEXT: "parentContexts":[{"kind":"objective-c.struct","name":"Foo","usr":"c:@S@Foo"}] +// CHECK-SAME: "relatedSymbols":[] +// CHECK-SAME: "relationships":[{"kind":"memberOf","source":"c:@S@Foo@FI@bar","target":"c:@S@Foo" +// CHECK-SAME: "text":"Bar docs" +// CHECK-SAME: "kind":{"displayName":"Instance Property","identifier":"objective-c.property"} +// CHECK-SAME: "title":"bar" + +// Checking for Base +// CHECK-NEXT: "parentContexts":[] +// CHECK-SAME: "relatedSymbols":[] +// CHECK-SAME: "relationships":[] +// CHECK-SAME: "text":"Base docs" +// CHECK-SAME: "kind":{"displayName":"Class","identifier":"objective-c.class"} +// CHECK-SAME: "title":"Base" + +// Checking for baseProperty +// CHECK-NEXT: "parentContexts":[{"kind":"objective-c.class","name":"Base","usr":"c:objc(cs)Base"}] +// CHECK-SAME: "relatedSymbols":[{"accessLevel":"public","declarationLanguage":"objective-c" +// CHECK-SAME: "isSystem":false +// CHECK-SAME: "usr":"c:@S@Foo"}] +// CHECK-SAME: "relationships":[{"kind":"memberOf","source":"c:objc(cs)Base(py)baseProperty","target":"c:objc(cs)Base" +// CHECK-SAME: "text":"Base property docs" +// CHECK-SAME: "kind":{"displayName":"Instance Property","identifier":"objective-c.property"} +// CHECK-SAME: "title":"baseProperty" + +// Checking for baseMethodWithArg +// CHECK-NEXT: "parentContexts":[{"kind":"objective-c.class","name":"Base","usr":"c:objc(cs)Base"}] +// CHECK-SAME: "relatedSymbols":[] +// CHECK-SAME: "relationships":[{"kind":"memberOf","source":"c:objc(cs)Base(im)baseMethodWithArg:","target":"c:objc(cs)Base" +// CHECK-SAME: "text":"Base method docs" +// CHECK-SAME: "kind":{"displayName":"Instance Method","identifier":"objective-c.method"} +// CHECK-SAME: "title":"baseMethodWithArg:" + +// Checking for Protocol +// CHECK-NEXT: "parentContexts":[] +// CHECK-SAME: "relatedSymbols":[] +// CHECK-SAME: "relationships":[] +// CHECK-SAME: "text":"Protocol docs" +// CHECK-SAME: "kind":{"displayName":"Protocol","identifier":"objective-c.protocol"} +// CHECK-SAME: "title":"Protocol" + +// Checking for protocolProperty +// CHECK-NEXT: "parentContexts":[{"kind":"objective-c.protocol","name":"Protocol","usr":"c:objc(pl)Protocol"}] +// CHECK-SAME: "relatedSymbols":[{"accessLevel":"public","declarationLanguage":"objective-c" +// CHECK-SAME: "isSystem":false +// CHECK-SAME: "usr":"c:@S@Foo"}] +// CHECK-SAME: "relationships":[{"kind":"memberOf","source":"c:objc(pl)Protocol(py)protocolProperty","target":"c:objc(pl)Protocol" +// CHECK-SAME: "text":"Protocol property docs" +// CHECK-SAME: "kind":{"displayName":"Instance Property","identifier":"objective-c.property"} +// CHECK-SAME: "title":"protocolProperty" + +// Checking for Derived +// CHECK-NEXT: "parentContexts":[] +// CHECK-SAME: "relatedSymbols":[{"accessLevel":"public","declarationLanguage":"objective-c" +// CHECK-SAME: "isSystem":false +// CHECK-SAME: "usr":"c:objc(cs)Base"}] +// CHECK-SAME: "relationships":[{"kind":"inheritsFrom","source":"c:objc(cs)Derived","target":"c:objc(cs)Base" +// CHECK-SAME: "text":"Derived docs" +// CHECK-SAME: "kind":{"displayName":"Class","identifier":"objective-c.class"} +// CHECK-SAME: "title":"Derived" + +// Checking for derivedMethodWithValue +// CHECK-NEXT: "parentContexts":[{"kind":"objective-c.class","name":"Derived","usr":"c:objc(cs)Derived"}] +// CHECK-SAME: "relatedSymbols":[] +// CHECK-SAME: "relationships":[{"kind":"memberOf","source":"c:objc(cs)Derived(im)derivedMethodWithValue:","target":"c:objc(cs)Derived" +// CHECK-SAME: "text":"Derived method docs" +// CHECK-SAME: "kind":{"displayName":"Instance Method","identifier":"objective-c.method"} +// CHECK-SAME: "title":"derivedMethodWithValue:" + +// CHECK-NOT: This won't show up in docs because we can't serialize it +// CHECK-NOT: Derived method in category docs, won't show up either. diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c index f116111..448435e 100644 --- a/clang/tools/c-index-test/c-index-test.c +++ b/clang/tools/c-index-test/c-index-test.c @@ -3,7 +3,6 @@ #include "clang-c/BuildSystem.h" #include "clang-c/CXCompilationDatabase.h" #include "clang-c/CXErrorCode.h" -#include "clang-c/CXSourceLocation.h" #include "clang-c/CXString.h" #include "clang-c/Documentation.h" #include "clang-c/Index.h" @@ -4882,21 +4881,6 @@ dispose_index: return result; } -static void inspect_single_symbol_sgf_cursor(CXCursor Cursor) { - CXSourceLocation CursorLoc; - CXString SGFData; - const char *SGF; - unsigned line, column; - CursorLoc = clang_getCursorLocation(Cursor); - clang_getSpellingLocation(CursorLoc, 0, &line, &column, 0); - printf("%d:%d: ", line, column); - - SGFData = clang_getSymbolGraphForCursor(Cursor); - SGF = clang_getCString(SGFData); - if (SGF) - printf("%s\n", SGF); -} - /******************************************************************************/ /* Command line processing. */ /******************************************************************************/ @@ -4956,7 +4940,6 @@ static void print_usage(void) { " c-index-test -print-usr-file \n"); fprintf(stderr, " c-index-test -single-symbol-sgfs {*}\n" - " c-index-test -single-symbol-sgf-at= {*}\n" " c-index-test -single-symbol-sgf-for= {}*\n"); fprintf(stderr, " c-index-test -write-pch \n" @@ -5093,9 +5076,6 @@ int cindextest_main(int argc, const char **argv) { else if (argc > 3 && strcmp(argv[1], "-single-symbol-sgfs") == 0) return perform_test_load_source(argc - 3, argv + 3, argv[2], PrintSingleSymbolSGFs, NULL); - else if (argc > 2 && strstr(argv[1], "-single-symbol-sgf-at=") == argv[1]) - return inspect_cursor_at( - argc, argv, "-single-symbol-sgf-at=", inspect_single_symbol_sgf_cursor); else if (argc > 2 && strstr(argv[1], "-single-symbol-sgf-for=") == argv[1]) return perform_test_single_symbol_sgf(argv[1], argc - 2, argv + 2); diff --git a/clang/tools/libclang/CXExtractAPI.cpp b/clang/tools/libclang/CXExtractAPI.cpp index 9128e89..787334a 100644 --- a/clang/tools/libclang/CXExtractAPI.cpp +++ b/clang/tools/libclang/CXExtractAPI.cpp @@ -18,7 +18,6 @@ #include "clang-c/Index.h" #include "clang-c/Platform.h" #include "clang/AST/Decl.h" -#include "clang/AST/DeclObjC.h" #include "clang/Basic/TargetInfo.h" #include "clang/ExtractAPI/API.h" #include "clang/ExtractAPI/ExtractAPIVisitor.h" @@ -35,73 +34,13 @@ using namespace clang; using namespace clang::extractapi; -namespace { -struct LibClangExtractAPIVisitor - : ExtractAPIVisitor { - using Base = ExtractAPIVisitor; - - LibClangExtractAPIVisitor(ASTContext &Context, APISet &API) - : ExtractAPIVisitor(Context, API) {} - - const RawComment *fetchRawCommentForDecl(const Decl *D) const { - return Context.getRawCommentForAnyRedecl(D); - } - - // We need to visit implementations as well to ensure that when a user clicks - // on a method defined only within the implementation that we can still - // provide a symbol graph for it. - bool VisitObjCImplementationDecl(const ObjCImplementationDecl *Decl) { - if (!shouldDeclBeIncluded(Decl)) - return true; - - const ObjCInterfaceDecl *Interface = Decl->getClassInterface(); - StringRef Name = Interface->getName(); - StringRef USR = API.recordUSR(Decl); - PresumedLoc Loc = - Context.getSourceManager().getPresumedLoc(Decl->getLocation()); - LinkageInfo Linkage = Decl->getLinkageAndVisibility(); - DocComment Comment; - if (auto *RawComment = fetchRawCommentForDecl(Interface)) - Comment = RawComment->getFormattedLines(Context.getSourceManager(), - Context.getDiagnostics()); - - // Build declaration fragments and sub-heading by generating them for the - // interface. - DeclarationFragments Declaration = - DeclarationFragmentsBuilder::getFragmentsForObjCInterface(Interface); - 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(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()); - - return true; - } -}; -} // namespace - DEFINE_SIMPLE_CONVERSION_FUNCTIONS(APISet, CXAPISet) -static void WalkupFromMostDerivedType(LibClangExtractAPIVisitor &Visitor, - Decl *D); +static void WalkupFromMostDerivedType(ExtractAPIVisitor &Visitor, Decl *D); template static bool WalkupParentContext(DeclContext *Parent, - LibClangExtractAPIVisitor &Visitor) { + ExtractAPIVisitor &Visitor) { if (auto *D = dyn_cast(Parent)) { WalkupFromMostDerivedType(Visitor, D); return true; @@ -109,8 +48,7 @@ static bool WalkupParentContext(DeclContext *Parent, return false; } -static void WalkupFromMostDerivedType(LibClangExtractAPIVisitor &Visitor, - Decl *D) { +static void WalkupFromMostDerivedType(ExtractAPIVisitor &Visitor, Decl *D) { switch (D->getKind()) { #define ABSTRACT_DECL(DECL) #define DECL(CLASS, BASE) \ @@ -146,7 +84,8 @@ enum CXErrorCode clang_createAPISet(CXTranslationUnit tu, CXAPISet *out_api) { auto Lang = Unit->getInputKind().getLanguage(); APISet *API = new APISet(Ctx.getTargetInfo().getTriple(), Lang, Unit->getMainFileName().str()); - LibClangExtractAPIVisitor Visitor(Ctx, *API); + ExtractAPIVisitor Visitor( + Ctx, [](SourceLocation Loc) { return true; }, *API); for (auto It = Unit->top_level_begin(); It != Unit->top_level_end(); ++It) { Visitor.TraverseDecl(*It); @@ -168,50 +107,45 @@ CXString clang_getSymbolGraphForUSR(const char *usr, CXAPISet api) { } CXString clang_getSymbolGraphForCursor(CXCursor cursor) { - cursor = clang_getCursorReferenced(cursor); CXCursorKind Kind = clang_getCursorKind(cursor); - if (!clang_isDeclaration(Kind)) - return cxstring::createNull(); + if (clang_isDeclaration(Kind)) { + const Decl *D = cxcursor::getCursorDecl(cursor); - const Decl *D = cxcursor::getCursorDecl(cursor); + if (!D) + return cxstring::createNull(); - if (!D) - return cxstring::createNull(); + CXTranslationUnit TU = cxcursor::getCursorTU(cursor); + if (!TU) + return cxstring::createNull(); - CXTranslationUnit TU = cxcursor::getCursorTU(cursor); - if (!TU) - return cxstring::createNull(); + ASTUnit *Unit = cxtu::getASTUnit(TU); - ASTUnit *Unit = cxtu::getASTUnit(TU); + auto &Ctx = Unit->getASTContext(); + auto Lang = Unit->getInputKind().getLanguage(); + APISet API(Ctx.getTargetInfo().getTriple(), Lang, + Unit->getMainFileName().str()); + ExtractAPIVisitor Visitor( + Ctx, [](SourceLocation Loc) { return true; }, API); - auto &Ctx = Unit->getASTContext(); - - auto Lang = Unit->getInputKind().getLanguage(); - APISet API(Ctx.getTargetInfo().getTriple(), Lang, - Unit->getMainFileName().str()); - LibClangExtractAPIVisitor Visitor(Ctx, API); + SmallString<128> USR; + if (index::generateUSRForDecl(D, USR)) + return cxstring::createNull(); - const Decl *CanonicalDecl = D->getCanonicalDecl(); - CanonicalDecl = CanonicalDecl ? CanonicalDecl : D; + WalkupFromMostDerivedType(Visitor, const_cast(D)); + auto *Record = API.findRecordForUSR(USR); - SmallString<128> USR; - if (index::generateUSRForDecl(CanonicalDecl, USR)) - return cxstring::createNull(); + if (!Record) + return cxstring::createNull(); - WalkupFromMostDerivedType(Visitor, const_cast(CanonicalDecl)); - auto *Record = API.findRecordForUSR(USR); - - if (!Record) - return cxstring::createNull(); + for (const auto &Fragment : Record->Declaration.getFragments()) { + if (Fragment.Declaration) + WalkupFromMostDerivedType(Visitor, + const_cast(Fragment.Declaration)); + } - for (const auto &Fragment : Record->Declaration.getFragments()) { - if (Fragment.Declaration) - WalkupFromMostDerivedType(Visitor, - const_cast(Fragment.Declaration)); + if (auto SGF = SymbolGraphSerializer::serializeSingleSymbolSGF(USR, API)) + return GenerateCXStringFromSymbolGraphData(std::move(*SGF)); } - if (auto SGF = SymbolGraphSerializer::serializeSingleSymbolSGF(USR, API)) - return GenerateCXStringFromSymbolGraphData(std::move(*SGF)); - return cxstring::createNull(); } -- 2.7.4