evelez7 created this revision. evelez7 added a reviewer: dang. Herald added a reviewer: ributzka. Herald added a project: All. evelez7 requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
Refactor visitation for C++ record children by following the Visitor's CRTP. Expand VisitCXXField, VisitCXXMethod for non-templates and introduce VisitCXXConstructor, VisitCXXDestructor. Handle relationships by finding the parent's Record via USR from DeclContext. Depends on D158029 <https://reviews.llvm.org/D158029> Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D158031 Files: clang/include/clang/ExtractAPI/API.h clang/include/clang/ExtractAPI/ExtractAPIVisitor.h clang/include/clang/ExtractAPI/Serialization/SerializerBase.h clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h clang/lib/ExtractAPI/API.cpp clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp clang/test/ExtractAPI/constructor_destructor.cpp clang/test/ExtractAPI/methods.cpp
Index: clang/test/ExtractAPI/methods.cpp =================================================================== --- clang/test/ExtractAPI/methods.cpp +++ clang/test/ExtractAPI/methods.cpp @@ -64,13 +64,13 @@ }, { "kind": "memberOf", - "source": "c:@S@Foo@F@getFoo#S", + "source": "c:@S@Foo@F@getBar#1", "target": "c:@S@Foo", "targetFallback": "Foo" }, { "kind": "memberOf", - "source": "c:@S@Foo@F@getBar#1", + "source": "c:@S@Foo@F@getFoo#S", "target": "c:@S@Foo", "targetFallback": "Foo" } @@ -310,11 +310,11 @@ ] }, { - "accessLevel": "public", + "accessLevel": "protected", "declarationFragments": [ { "kind": "keyword", - "spelling": "static" + "spelling": "constexpr" }, { "kind": "text", @@ -322,8 +322,8 @@ }, { "kind": "typeIdentifier", - "preciseIdentifier": "c:d", - "spelling": "double" + "preciseIdentifier": "c:I", + "spelling": "int" }, { "kind": "text", @@ -331,34 +331,42 @@ }, { "kind": "identifier", - "spelling": "getFoo" + "spelling": "getBar" }, { "kind": "text", - "spelling": "();" + "spelling": "() " + }, + { + "kind": "keyword", + "spelling": "const" + }, + { + "kind": "text", + "spelling": ";" } ], "functionSignature": { "returns": [ { "kind": "typeIdentifier", - "preciseIdentifier": "c:d", - "spelling": "double" + "preciseIdentifier": "c:I", + "spelling": "int" } ] }, "identifier": { "interfaceLanguage": "c++", - "precise": "c:@S@Foo@F@getFoo#S" + "precise": "c:@S@Foo@F@getBar#1" }, "kind": { - "displayName": "Static Method", - "identifier": "c++.type.method" + "displayName": "Instance Method", + "identifier": "c++.method" }, "location": { "position": { "character": 17, - "line": 7 + "line": 10 }, "uri": "file://INPUT_DIR/input.h" }, @@ -366,28 +374,28 @@ "navigator": [ { "kind": "identifier", - "spelling": "getFoo" + "spelling": "getBar" } ], "subHeading": [ { "kind": "identifier", - "spelling": "getFoo" + "spelling": "getBar" } ], - "title": "getFoo" + "title": "getBar" }, "pathComponents": [ "Foo", - "getFoo" + "getBar" ] }, { - "accessLevel": "protected", + "accessLevel": "public", "declarationFragments": [ { "kind": "keyword", - "spelling": "constexpr" + "spelling": "static" }, { "kind": "text", @@ -395,8 +403,8 @@ }, { "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" + "preciseIdentifier": "c:d", + "spelling": "double" }, { "kind": "text", @@ -404,42 +412,34 @@ }, { "kind": "identifier", - "spelling": "getBar" - }, - { - "kind": "text", - "spelling": "() " - }, - { - "kind": "keyword", - "spelling": "const" + "spelling": "getFoo" }, { "kind": "text", - "spelling": ";" + "spelling": "();" } ], "functionSignature": { "returns": [ { "kind": "typeIdentifier", - "preciseIdentifier": "c:I", - "spelling": "int" + "preciseIdentifier": "c:d", + "spelling": "double" } ] }, "identifier": { "interfaceLanguage": "c++", - "precise": "c:@S@Foo@F@getBar#1" + "precise": "c:@S@Foo@F@getFoo#S" }, "kind": { - "displayName": "Instance Method", - "identifier": "c++.method" + "displayName": "Static Method", + "identifier": "c++.type.method" }, "location": { "position": { "character": 17, - "line": 10 + "line": 7 }, "uri": "file://INPUT_DIR/input.h" }, @@ -447,20 +447,20 @@ "navigator": [ { "kind": "identifier", - "spelling": "getBar" + "spelling": "getFoo" } ], "subHeading": [ { "kind": "identifier", - "spelling": "getBar" + "spelling": "getFoo" } ], - "title": "getBar" + "title": "getFoo" }, "pathComponents": [ "Foo", - "getBar" + "getFoo" ] } ] Index: clang/test/ExtractAPI/constructor_destructor.cpp =================================================================== --- clang/test/ExtractAPI/constructor_destructor.cpp +++ clang/test/ExtractAPI/constructor_destructor.cpp @@ -137,7 +137,7 @@ "precise": "c:@S@Foo@F@Foo#" }, "kind": { - "displayName": "Constructor", + "displayName": "Instance Method", "identifier": "c++.method" }, "location": { @@ -193,7 +193,7 @@ "precise": "c:@S@Foo@F@~Foo#" }, "kind": { - "displayName": "Destructor", + "displayName": "Instance Method", "identifier": "c++.method" }, "location": { Index: clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp =================================================================== --- clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -872,9 +872,6 @@ return; Symbols.emplace_back(std::move(*Class)); - serializeMembers(Record, Record.Fields); - serializeMembers(Record, Record.Methods); - for (const auto Base : Record.Bases) serializeRelationship(RelationshipKind::InheritsFrom, Record, Base); } @@ -886,9 +883,6 @@ return; Symbols.emplace_back(std::move(*Class)); - serializeMembers(Record, Record.Fields); - serializeMembers(Record, Record.Methods); - for (const auto Base : Record.Bases) serializeRelationship(RelationshipKind::InheritsFrom, Record, Base); } @@ -900,8 +894,6 @@ return; Symbols.emplace_back(std::move(*Class)); - serializeMembers(Record, Record.Fields); - serializeMembers(Record, Record.Methods); for (const auto Base : Record.Bases) serializeRelationship(RelationshipKind::InheritsFrom, Record, Base); @@ -914,13 +906,33 @@ return; Symbols.emplace_back(std::move(*Class)); - serializeMembers(Record, Record.Fields); - serializeMembers(Record, Record.Methods); for (const auto Base : Record.Bases) serializeRelationship(RelationshipKind::InheritsFrom, Record, Base); } +void SymbolGraphSerializer::visitCXXInstanceMethodRecord( + const CXXInstanceMethodRecord &Record) { + auto InstanceMethod = serializeAPIRecord(Record); + if (!InstanceMethod) + return; + + Symbols.emplace_back(std::move(*InstanceMethod)); + serializeRelationship(RelationshipKind::MemberOf, Record, + Record.ParentInformation.ParentRecord); +} + +void SymbolGraphSerializer::visitCXXStaticMethodRecord( + const CXXStaticMethodRecord &Record) { + auto StaticMethod = serializeAPIRecord(Record); + if (!StaticMethod) + return; + + Symbols.emplace_back(std::move(*StaticMethod)); + serializeRelationship(RelationshipKind::MemberOf, Record, + Record.ParentInformation.ParentRecord); +} + void SymbolGraphSerializer::visitMethodTemplateRecord( const CXXMethodTemplateRecord &Record) { if (!ShouldRecurse) @@ -947,6 +959,17 @@ Record.ParentInformation.ParentRecord); } +void SymbolGraphSerializer::visitCXXFieldRecord(const CXXFieldRecord &Record) { + if (!ShouldRecurse) + return; + auto CXXField = serializeAPIRecord(Record); + if (!CXXField) + return; + Symbols.emplace_back(std::move(*CXXField)); + serializeRelationship(RelationshipKind::MemberOf, Record, + Record.ParentInformation.ParentRecord); +} + void SymbolGraphSerializer::visitCXXFieldTemplateRecord( const CXXFieldTemplateRecord &Record) { if (!ShouldRecurse) @@ -1002,7 +1025,7 @@ void SymbolGraphSerializer::visitGlobalFunctionTemplateSpecRecord( const GlobalFunctionTemplateSpecRecord &Record) { - auto GlobalFunctionTemplateSpec= serializeAPIRecord(Record); + auto GlobalFunctionTemplateSpec = serializeAPIRecord(Record); if (!GlobalFunctionTemplateSpec) return; Symbols.emplace_back(std::move(*GlobalFunctionTemplateSpec)); Index: clang/lib/ExtractAPI/API.cpp =================================================================== --- clang/lib/ExtractAPI/API.cpp +++ clang/lib/ExtractAPI/API.cpp @@ -170,18 +170,17 @@ } CXXFieldRecord * -APISet::addCXXField(CXXClassRecord *CXXClass, StringRef Name, StringRef USR, +APISet::addCXXField(APIRecord *CXXClass, StringRef Name, StringRef USR, PresumedLoc Loc, AvailabilitySet Availabilities, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, AccessControl Access, bool IsFromSystemHeader) { - auto Record = std::make_unique<CXXFieldRecord>( - USR, Name, Loc, std::move(Availabilities), Comment, Declaration, - SubHeading, Access, IsFromSystemHeader); + auto *Record = addTopLevelRecord( + USRBasedLookupTable, CXXFields, USR, Name, Loc, std::move(Availabilities), + Comment, Declaration, SubHeading, Access, IsFromSystemHeader); Record->ParentInformation = APIRecord::HierarchyInformation( CXXClass->USR, CXXClass->Name, CXXClass->getKind(), CXXClass); - USRBasedLookupTable.insert({USR, Record.get()}); - return CXXClass->Fields.emplace_back(std::move(Record)).get(); + return Record; } CXXFieldTemplateRecord *APISet::addCXXFieldTemplate( @@ -277,50 +276,38 @@ SubHeading, Template, IsFromSystemHeader); } -CXXMethodRecord *APISet::addCXXMethod( - CXXClassRecord *CXXClassRecord, StringRef Name, StringRef USR, - PresumedLoc Loc, AvailabilitySet Availability, const DocComment &Comment, +CXXMethodRecord *APISet::addCXXInstanceMethod( + APIRecord *CXXClassRecord, StringRef Name, StringRef USR, PresumedLoc Loc, + AvailabilitySet Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, - FunctionSignature Signature, bool IsStatic, AccessControl Access, + FunctionSignature Signature, AccessControl Access, bool IsFromSystemHeader) { - std::unique_ptr<CXXMethodRecord> Record; - if (IsStatic) - Record = std::make_unique<CXXStaticMethodRecord>( - USR, Name, Loc, std::move(Availability), Comment, Declaration, - SubHeading, Signature, Access, IsFromSystemHeader); - else - Record = std::make_unique<CXXInstanceMethodRecord>( - USR, Name, Loc, std::move(Availability), Comment, Declaration, - SubHeading, Signature, Access, IsFromSystemHeader); + CXXMethodRecord *Record = + addTopLevelRecord(USRBasedLookupTable, CXXInstanceMethods, USR, Name, Loc, + std::move(Availability), Comment, Declaration, + SubHeading, Signature, Access, IsFromSystemHeader); Record->ParentInformation = APIRecord::HierarchyInformation( CXXClassRecord->USR, CXXClassRecord->Name, CXXClassRecord->getKind(), CXXClassRecord); - USRBasedLookupTable.insert({USR, Record.get()}); - return CXXClassRecord->Methods.emplace_back(std::move(Record)).get(); + return Record; } -CXXMethodRecord *APISet::addCXXSpecialMethod( - CXXClassRecord *CXXClassRecord, StringRef Name, StringRef USR, - PresumedLoc Loc, AvailabilitySet Availability, const DocComment &Comment, +CXXMethodRecord *APISet::addCXXStaticMethod( + APIRecord *CXXClassRecord, StringRef Name, StringRef USR, PresumedLoc Loc, + AvailabilitySet Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, - FunctionSignature Signature, bool IsConstructor, AccessControl Access, + FunctionSignature Signature, AccessControl Access, bool IsFromSystemHeader) { - std::unique_ptr<CXXMethodRecord> Record; - if (IsConstructor) - Record = std::make_unique<CXXConstructorRecord>( - USR, Name, Loc, std::move(Availability), Comment, Declaration, - SubHeading, Signature, Access, IsFromSystemHeader); - else - Record = std::make_unique<CXXDestructorRecord>( - USR, Name, Loc, std::move(Availability), Comment, Declaration, - SubHeading, Signature, Access, IsFromSystemHeader); + CXXMethodRecord *Record = + addTopLevelRecord(USRBasedLookupTable, CXXStaticMethods, USR, Name, Loc, + std::move(Availability), Comment, Declaration, + SubHeading, Signature, Access, IsFromSystemHeader); Record->ParentInformation = APIRecord::HierarchyInformation( CXXClassRecord->USR, CXXClassRecord->Name, CXXClassRecord->getKind(), CXXClassRecord); - USRBasedLookupTable.insert({USR, Record.get()}); - return CXXClassRecord->Methods.emplace_back(std::move(Record)).get(); + return Record; } CXXMethodTemplateRecord *APISet::addCXXMethodTemplate( Index: clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h =================================================================== --- clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h +++ clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h @@ -175,10 +175,16 @@ void visitClassTemplatePartialSpecRecord( const ClassTemplatePartialSpecRecord &Record); + void visitCXXInstanceMethodRecord(const CXXInstanceMethodRecord &Record); + + void visitCXXStaticMethodRecord(const CXXStaticMethodRecord &Record); + void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record); void visitMethodTemplateSpecRecord(const CXXMethodTemplateSpecRecord &Record); + void visitCXXFieldRecord(const CXXFieldRecord &Record); + void visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord &Record); void visitConceptRecord(const ConceptRecord &Record); Index: clang/include/clang/ExtractAPI/Serialization/SerializerBase.h =================================================================== --- clang/include/clang/ExtractAPI/Serialization/SerializerBase.h +++ clang/include/clang/ExtractAPI/Serialization/SerializerBase.h @@ -39,10 +39,16 @@ getDerived()->traverseClassTemplatePartialSpecRecords(); + getDerived()->traverseCXXInstanceMethods(); + + getDerived()->traverseCXXStaticMethods(); + getDerived()->traverseCXXMethodTemplates(); getDerived()->traverseCXXMethodTemplateSpecializations(); + getDerived()->traverseCXXFields(); + getDerived()->traverseCXXFieldTemplates(); getDerived()->traverseConcepts(); @@ -126,6 +132,21 @@ *ClassTemplatePartialSpec.second); } + void traverseCXXInstanceMethods() { + for (const auto &InstanceMethod : API.getCXXInstanceMethods()) + getDerived()->visitCXXInstanceMethodRecord(*InstanceMethod.second); + } + + void traverseCXXStaticMethods() { + for (const auto &InstanceMethod : API.getCXXStaticMethods()) + getDerived()->visitCXXStaticMethodRecord(*InstanceMethod.second); + } + + void traverseCXXFields() { + for (const auto &CXXField : API.getCXXFields()) + getDerived()->visitCXXFieldRecord(*CXXField.second); + } + void traverseCXXFieldTemplates() { for (const auto &CXXFieldTemplate : API.getCXXFieldTemplates()) getDerived()->visitCXXFieldTemplateRecord(*CXXFieldTemplate.second); @@ -212,6 +233,10 @@ void visitClassTemplatePartialSpecRecord( const ClassTemplatePartialSpecRecord &Record){}; + void visitCXXInstanceRecord(const CXXInstanceMethodRecord &Record){}; + + void visitCXXStaticRecord(const CXXStaticMethodRecord &Record){}; + void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record){}; void Index: clang/include/clang/ExtractAPI/ExtractAPIVisitor.h =================================================================== --- clang/include/clang/ExtractAPI/ExtractAPIVisitor.h +++ clang/include/clang/ExtractAPI/ExtractAPIVisitor.h @@ -50,6 +50,8 @@ bool VisitEnumDecl(const EnumDecl *Decl); + bool WalkUpFromFunctionDecl(const FunctionDecl *Decl); + bool WalkUpFromRecordDecl(const RecordDecl *Decl); bool WalkUpFromCXXRecordDecl(const CXXRecordDecl *Decl); @@ -78,6 +80,14 @@ bool VisitCXXMethodDecl(const CXXMethodDecl *Decl); + bool VisitFieldDecl(const FieldDecl *Decl); + + bool VisitCXXConversionDecl(const CXXConversionDecl *Decl); + + bool VisitCXXConstructorDecl(const CXXConstructorDecl *Decl); + + bool VisitCXXDestructorDecl(const CXXDestructorDecl *Decl); + bool VisitConceptDecl(const ConceptDecl *Decl); bool VisitClassTemplateSpecializationDecl( @@ -119,20 +129,6 @@ void recordStructFields(StructRecord *StructRecord, const RecordDecl::field_range Fields); - /// Collect API information for the class fields and associate with the parent - /// struct - void recordCXXFields(CXXClassRecord *CXXClassRecord, - const RecordDecl::field_range Fields); - - void recordCXXMethods(CXXClassRecord *CXXClassRecord, - const CXXRecordDecl::method_range Methods); - - void recordConversionMethod(CXXClassRecord *CXXClassRecord, - const CXXMethodDecl *SpecialCXXMethod); - - void recordSpecialCXXMethod(CXXClassRecord *CXXClassRecord, - const CXXMethodDecl *SpecialCXXMethod); - /// Collect API information for the Objective-C methods and associate with the /// parent container. void recordObjCMethods(ObjCContainerRecord *Container, @@ -355,6 +351,13 @@ return true; } +template <typename Derived> +bool ExtractAPIVisitorBase<Derived>::WalkUpFromFunctionDecl( + const FunctionDecl *Decl) { + getDerivedExtractAPIVisitor().VisitFunctionDecl(Decl); + return true; +} + template <typename Derived> bool ExtractAPIVisitorBase<Derived>::WalkUpFromRecordDecl( const RecordDecl *Decl) { @@ -518,9 +521,6 @@ CXXClassRecord->Bases.emplace_back(BaseClass); } - getDerivedExtractAPIVisitor().recordCXXFields(CXXClassRecord, Decl->fields()); - getDerivedExtractAPIVisitor().recordCXXMethods(CXXClassRecord, - Decl->methods()); return true; } @@ -530,18 +530,12 @@ if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) || Decl->isImplicit()) return true; - switch (Decl->getTemplatedKind()) { - case FunctionDecl::TK_MemberSpecialization: - case FunctionDecl::TK_FunctionTemplateSpecialization: - case FunctionDecl::TK_FunctionTemplate: - case FunctionDecl::TK_DependentFunctionTemplateSpecialization: - break; - case FunctionDecl::TK_NonTemplate: - case FunctionDecl::TK_DependentNonTemplate: + + if (isa<CXXConversionDecl>(Decl)) + return true; + if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl)) return true; - } - StringRef Name = Decl->getName(); StringRef USR = API.recordUSR(Decl); PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); @@ -552,15 +546,18 @@ Context.getDiagnostics()); DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); + auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl); + auto Signature = DeclarationFragmentsBuilder::getFunctionSignature(Decl); SmallString<128> ParentUSR; index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()), ParentUSR); + auto *Parent = API.findRecordForUSR(ParentUSR); if (Decl->isTemplated()) { FunctionTemplateDecl *Template = Decl->getDescribedFunctionTemplate(); API.addCXXMethodTemplate( - API.findRecordForUSR(ParentUSR), Name, USR, Loc, AvailabilitySet(Decl), - Comment, + API.findRecordForUSR(ParentUSR), Decl->getName(), USR, Loc, + AvailabilitySet(Decl), Comment, DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(Template), SubHeading, DeclarationFragmentsBuilder::getFunctionSignature(Decl), DeclarationFragmentsBuilder::getAccessControl(Template), @@ -568,13 +565,93 @@ isInSystemHeader(Decl)); } else if (Decl->getTemplateSpecializationInfo()) API.addCXXMethodTemplateSpec( - API.findRecordForUSR(ParentUSR), Name, USR, Loc, AvailabilitySet(Decl), - Comment, + Parent, Decl->getName(), USR, Loc, AvailabilitySet(Decl), Comment, DeclarationFragmentsBuilder:: getFragmentsForFunctionTemplateSpecialization(Decl), - SubHeading, DeclarationFragmentsBuilder::getFunctionSignature(Decl), - DeclarationFragmentsBuilder::getAccessControl(Decl), - isInSystemHeader(Decl)); + SubHeading, Signature, Access, isInSystemHeader(Decl)); + else if (Decl->isOverloadedOperator()) + API.addCXXInstanceMethod( + Parent, API.copyString(Decl->getNameAsString()), USR, Loc, + AvailabilitySet(Decl), Comment, + DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(Decl), + SubHeading, Signature, Access, isInSystemHeader(Decl)); + else if (Decl->isStatic()) + API.addCXXStaticMethod( + Parent, Decl->getName(), USR, Loc, AvailabilitySet(Decl), Comment, + DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Decl), SubHeading, + Signature, Access, isInSystemHeader(Decl)); + else + API.addCXXInstanceMethod( + Parent, Decl->getName(), USR, Loc, AvailabilitySet(Decl), Comment, + DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Decl), SubHeading, + Signature, Access, isInSystemHeader(Decl)); + + return true; +} + +template <typename Derived> +bool ExtractAPIVisitorBase<Derived>::VisitCXXConstructorDecl( + const CXXConstructorDecl *Decl) { + + StringRef Name = API.copyString(Decl->getNameAsString()); + 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, sub-heading, and signature for the method. + DeclarationFragments Declaration = + DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(Decl); + DeclarationFragments SubHeading = + DeclarationFragmentsBuilder::getSubHeading(Decl); + FunctionSignature Signature = + DeclarationFragmentsBuilder::getFunctionSignature(Decl); + AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl); + + SmallString<128> ParentUSR; + index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()), + ParentUSR); + API.addCXXInstanceMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc, + AvailabilitySet(Decl), Comment, Declaration, + SubHeading, Signature, Access, + isInSystemHeader(Decl)); + return true; +} + +template <typename Derived> +bool ExtractAPIVisitorBase<Derived>::VisitCXXDestructorDecl( + const CXXDestructorDecl *Decl) { + + StringRef Name = API.copyString(Decl->getNameAsString()); + 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, sub-heading, and signature for the method. + DeclarationFragments Declaration = + DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(Decl); + DeclarationFragments SubHeading = + DeclarationFragmentsBuilder::getSubHeading(Decl); + FunctionSignature Signature = + DeclarationFragmentsBuilder::getFunctionSignature(Decl); + AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl); + + SmallString<128> ParentUSR; + index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()), + ParentUSR); + API.addCXXInstanceMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc, + AvailabilitySet(Decl), Comment, Declaration, + SubHeading, Signature, Access, + isInSystemHeader(Decl)); return true; } @@ -637,10 +714,6 @@ ClassTemplateSpecializationRecord->Bases.emplace_back(BaseClass); } - getDerivedExtractAPIVisitor().recordCXXFields( - ClassTemplateSpecializationRecord, Decl->fields()); - getDerivedExtractAPIVisitor().recordCXXMethods( - ClassTemplateSpecializationRecord, Decl->methods()); return true; } @@ -681,10 +754,6 @@ ClassTemplatePartialSpecRecord->Bases.emplace_back(BaseClass); } - getDerivedExtractAPIVisitor().recordCXXFields(ClassTemplatePartialSpecRecord, - Decl->fields()); - getDerivedExtractAPIVisitor().recordCXXMethods(ClassTemplatePartialSpecRecord, - Decl->methods()); return true; } @@ -1067,155 +1136,74 @@ } template <typename Derived> -void ExtractAPIVisitorBase<Derived>::recordCXXFields( - CXXClassRecord *CXXClassRecord, 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()); - 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); - AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Field); - - API.addCXXField(CXXClassRecord, Name, USR, Loc, AvailabilitySet(Field), - Comment, Declaration, SubHeading, Access, - isInSystemHeader(Field)); - } -} - -/// Collect API information for constructors and destructors and associate with -/// the parent class. -template <typename Derived> -void ExtractAPIVisitorBase<Derived>::recordSpecialCXXMethod( - CXXClassRecord *CXXClassRecord, const CXXMethodDecl *CXXSpecialMethod) { - StringRef Name; - bool isConstructor = false; - if (isa<CXXConstructorDecl>(CXXSpecialMethod)) { - isConstructor = true; - Name = CXXClassRecord->Name; - } else if (isa<CXXDestructorDecl>(CXXSpecialMethod)) { - // Copy string to get name with '~'. - Name = API.copyString(CXXSpecialMethod->getNameAsString()); - } - - StringRef USR = API.recordUSR(CXXSpecialMethod); - PresumedLoc Loc = Context.getSourceManager().getPresumedLoc( - CXXSpecialMethod->getLocation()); +bool ExtractAPIVisitorBase<Derived>::VisitFieldDecl(const FieldDecl *Decl) { + if (Decl->getDeclContext()->getDeclKind() == Decl::Record) + return true; + if (isa<ObjCIvarDecl>(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( - CXXSpecialMethod)) + if (auto *RawComment = + getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) Comment = RawComment->getFormattedLines(Context.getSourceManager(), Context.getDiagnostics()); - // Build declaration fragments, sub-heading, and signature for the method. + // Build declaration fragments and sub-heading for the struct field. DeclarationFragments Declaration = - DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod( - CXXSpecialMethod); + DeclarationFragmentsBuilder::getFragmentsForField(Decl); DeclarationFragments SubHeading = - DeclarationFragmentsBuilder::getSubHeading(CXXSpecialMethod); - FunctionSignature Signature = - DeclarationFragmentsBuilder::getFunctionSignature(CXXSpecialMethod); - AccessControl Access = - DeclarationFragmentsBuilder::getAccessControl(CXXSpecialMethod); - - API.addCXXSpecialMethod(CXXClassRecord, Name, USR, Loc, - AvailabilitySet(CXXSpecialMethod), Comment, - Declaration, SubHeading, Signature, isConstructor, - Access, isInSystemHeader(CXXSpecialMethod)); + DeclarationFragmentsBuilder::getSubHeading(Decl); + AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl); + + SmallString<128> ParentUSR; + index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()), + ParentUSR); + API.addCXXField(API.findRecordForUSR(ParentUSR), Name, USR, Loc, + AvailabilitySet(Decl), Comment, Declaration, SubHeading, + Access, isInSystemHeader(Decl)); + return true; } template <typename Derived> -void ExtractAPIVisitorBase<Derived>::recordConversionMethod( - CXXClassRecord *CXXClassRecord, const CXXMethodDecl *SpecialCXXMethod) { - StringRef Name = API.copyString(SpecialCXXMethod->getNameAsString()); - StringRef USR = API.recordUSR(SpecialCXXMethod); - PresumedLoc Loc = Context.getSourceManager().getPresumedLoc( - SpecialCXXMethod->getLocation()); +bool ExtractAPIVisitorBase<Derived>::VisitCXXConversionDecl( + const CXXConversionDecl *Decl) { + StringRef Name = API.copyString(Decl->getNameAsString()); + StringRef USR = API.recordUSR(Decl); + PresumedLoc Loc = + Context.getSourceManager().getPresumedLoc(Decl->getLocation()); DocComment Comment; - if (auto *RawComment = getDerivedExtractAPIVisitor().fetchRawCommentForDecl( - SpecialCXXMethod)) + if (auto *RawComment = + getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) Comment = RawComment->getFormattedLines(Context.getSourceManager(), Context.getDiagnostics()); // Build declaration fragments, sub-heading, and signature for the method. DeclarationFragments Declaration = - DeclarationFragmentsBuilder::getFragmentsForConversionFunction( - cast<CXXConversionDecl>(SpecialCXXMethod)); + DeclarationFragmentsBuilder::getFragmentsForConversionFunction(Decl); DeclarationFragments SubHeading = - DeclarationFragmentsBuilder::getSubHeading(SpecialCXXMethod); + DeclarationFragmentsBuilder::getSubHeading(Decl); FunctionSignature Signature = - DeclarationFragmentsBuilder::getFunctionSignature(SpecialCXXMethod); - AccessControl Access = - DeclarationFragmentsBuilder::getAccessControl(SpecialCXXMethod); - - API.addCXXMethod(CXXClassRecord, Name, USR, Loc, - AvailabilitySet(SpecialCXXMethod), Comment, Declaration, - SubHeading, Signature, SpecialCXXMethod->isStatic(), Access, - isInSystemHeader(SpecialCXXMethod)); -} - -template <typename Derived> -void ExtractAPIVisitorBase<Derived>::recordCXXMethods( - CXXClassRecord *CXXClassRecord, const CXXRecordDecl::method_range Methods) { - for (const auto *Method : Methods) { - if (isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method)) { - recordSpecialCXXMethod(CXXClassRecord, Method); - continue; - } - - if (isa<CXXConversionDecl>(Method)) { - recordConversionMethod(CXXClassRecord, Method); - continue; - } - - if (Method->isFunctionTemplateSpecialization()) - return; - - StringRef Name; - DeclarationFragments Declaration; - if (Method->isOverloadedOperator()) { - Name = API.copyString(Method->getNameAsString()); - Declaration = - DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator( - Method); - } else { - Name = API.copyString(Method->getNameAsString()); - Declaration = - DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Method); - } - 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 SubHeading = - DeclarationFragmentsBuilder::getSubHeading(Method); - FunctionSignature Signature = - DeclarationFragmentsBuilder::getFunctionSignature(Method); - AccessControl Access = - DeclarationFragmentsBuilder::getAccessControl(Method); + DeclarationFragmentsBuilder::getFunctionSignature(Decl); + AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl); - API.addCXXMethod(CXXClassRecord, Name, USR, Loc, AvailabilitySet(Method), - Comment, Declaration, SubHeading, Signature, - Method->isStatic(), Access, isInSystemHeader(Method)); - } + SmallString<128> ParentUSR; + index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()), + ParentUSR); + if (Decl->isStatic()) + API.addCXXStaticMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc, + AvailabilitySet(Decl), Comment, Declaration, + SubHeading, Signature, Access, + isInSystemHeader(Decl)); + else + API.addCXXInstanceMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc, + AvailabilitySet(Decl), Comment, Declaration, + SubHeading, Signature, Access, + isInSystemHeader(Decl)); + return true; } /// Collect API information for the Objective-C methods and associate with the Index: clang/include/clang/ExtractAPI/API.h =================================================================== --- clang/include/clang/ExtractAPI/API.h +++ clang/include/clang/ExtractAPI/API.h @@ -1013,7 +1013,9 @@ template <> struct has_function_signature<ObjCClassMethodRecord> : public std::true_type {}; template <> -struct has_function_signature<CXXMethodRecord> : public std::true_type {}; +struct has_function_signature<CXXInstanceMethodRecord> : public std::true_type {}; +template <> +struct has_function_signature<CXXStaticMethodRecord> : public std::true_type {}; template <> struct has_function_signature<GlobalFunctionTemplateRecord> : public std::true_type {}; @@ -1028,7 +1030,8 @@ : public std::true_type {}; template <typename RecordTy> struct has_access : public std::false_type {}; -template <> struct has_access<CXXMethodRecord> : public std::true_type {}; +template <> struct has_access<CXXInstanceMethodRecord> : public std::true_type {}; +template <> struct has_access<CXXStaticMethodRecord> : public std::true_type {}; template <> struct has_access<CXXFieldRecord> : public std::true_type {}; template <> struct has_access<CXXMethodTemplateRecord> : public std::true_type {}; @@ -1159,7 +1162,7 @@ DeclarationFragments SubHeading, SymbolReference Context, AccessControl Access, bool IsFromSystemHeaderg); - CXXFieldRecord *addCXXField(CXXClassRecord *CXXClass, StringRef Name, + CXXFieldRecord *addCXXField(APIRecord *CXXClass, StringRef Name, StringRef USR, PresumedLoc Loc, AvailabilitySet Availabilities, const DocComment &Comment, @@ -1212,18 +1215,25 @@ DeclarationFragments SubHeading, Template Template, bool IsFromSystemHeader); - CXXMethodRecord * - addCXXMethod(CXXClassRecord *CXXClassRecord, StringRef Name, StringRef USR, - PresumedLoc Loc, AvailabilitySet Availability, - const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, FunctionSignature Signature, - bool IsStatic, AccessControl Access, bool IsFromSystemHeader); + CXXMethodRecord *addCXXInstanceMethod( + APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, + AvailabilitySet Availability, const DocComment &Comment, + DeclarationFragments Declaration, DeclarationFragments SubHeading, + FunctionSignature Signature, AccessControl Access, + bool IsFromSystemHeader); + + CXXMethodRecord *addCXXStaticMethod( + APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, + AvailabilitySet Availability, const DocComment &Comment, + DeclarationFragments Declaration, DeclarationFragments SubHeading, + FunctionSignature Signature, AccessControl Access, + bool IsFromSystemHeader); CXXMethodRecord *addCXXSpecialMethod( - CXXClassRecord *CXXClassRecord, StringRef Name, StringRef USR, - PresumedLoc Loc, AvailabilitySet Availability, const DocComment &Comment, + APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc, + AvailabilitySet Availability, const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, - FunctionSignature Signature, bool IsConstructor, AccessControl Access, + FunctionSignature Signature, AccessControl Access, bool IsFromSystemHeader); CXXMethodTemplateRecord *addCXXMethodTemplate( @@ -1398,6 +1408,13 @@ const RecordMap<CXXMethodTemplateRecord> &getCXXMethodTemplates() const { return CXXMethodTemplates; } + const RecordMap<CXXInstanceMethodRecord> &getCXXInstanceMethods() const { + return CXXInstanceMethods; + } + const RecordMap<CXXStaticMethodRecord> &getCXXStaticMethods() const { + return CXXStaticMethods; + } + const RecordMap<CXXFieldRecord> &getCXXFields() const { return CXXFields; } const RecordMap<CXXMethodTemplateSpecRecord> & getCXXMethodTemplateSpecializations() const { return CXXMethodTemplateSpecializations; @@ -1484,6 +1501,10 @@ RecordMap<EnumRecord> Enums; RecordMap<StructRecord> Structs; RecordMap<CXXClassRecord> CXXClasses; + RecordMap<CXXFieldRecord> CXXFields; + RecordMap<CXXMethodRecord> CXXMethods; + RecordMap<CXXInstanceMethodRecord> CXXInstanceMethods; + RecordMap<CXXStaticMethodRecord> CXXStaticMethods; RecordMap<CXXMethodTemplateRecord> CXXMethodTemplates; RecordMap<CXXMethodTemplateSpecRecord> CXXMethodTemplateSpecializations; RecordMap<CXXFieldTemplateRecord> CXXFieldTemplates;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits