brettw updated this revision to Diff 451299.
brettw marked an inline comment as done.
brettw added a comment.

I updated the comment test that's not currently working with a TODO.

There are some open questions in the code review about some bigger questions 
about this tool. Since this has been virtually abandoned for several years, I 
don't think anybody knows these answers and we're not going to figure out 
everything for this patch.

I think this patch makes things incrementally better and I'd like to land 
something soon so I can work on the next missing feature. I think over time we 
can build up knowledge about this tool and make it better on a wider scale. Can 
you please talk another look?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131298/new/

https://reviews.llvm.org/D131298

Files:
  clang-tools-extra/clang-doc/BitcodeReader.cpp
  clang-tools-extra/clang-doc/BitcodeWriter.cpp
  clang-tools-extra/clang-doc/Representation.h
  clang-tools-extra/clang-doc/Serialize.cpp
  clang-tools-extra/clang-doc/YAMLGenerator.cpp
  clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp
  clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp
  clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
  clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp

Index: clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp
===================================================================
--- clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp
+++ clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp
@@ -83,6 +83,19 @@
 
   I.Members.emplace_back("int", "path/to/int", "X",
                          AccessSpecifier::AS_private);
+
+  // Member documentation.
+  CommentInfo TopComment;
+  TopComment.Kind = "FullComment";
+  TopComment.Children.emplace_back(std::make_unique<CommentInfo>());
+  CommentInfo *Brief = TopComment.Children.back().get();
+  Brief->Kind = "ParagraphComment";
+  Brief->Children.emplace_back(std::make_unique<CommentInfo>());
+  Brief->Children.back()->Kind = "TextComment";
+  Brief->Children.back()->Name = "ParagraphComment";
+  Brief->Children.back()->Text = "Value of the thing.";
+  I.Members.back().Description.push_back(std::move(TopComment));
+
   I.TagType = TagTypeKind::TTK_Class;
   I.Bases.emplace_back(EmptySID, "F", "path/to/F", true,
                        AccessSpecifier::AS_public, true);
@@ -129,6 +142,14 @@
       Path:            'path/to/int'
     Name:            'X'
     Access:          Private
+    Description:
+      - Kind:            'FullComment'
+        Children:
+          - Kind:            'ParagraphComment'
+            Children:
+              - Kind:            'TextComment'
+                Text:            'Value of the thing.'
+                Name:            'ParagraphComment'
 Bases:
   - USR:             '0000000000000000000000000000000000000000'
     Name:            'F'
Index: clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
===================================================================
--- clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
+++ clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
@@ -80,6 +80,23 @@
   ASSERT_EQ(NumExpectedInfos, EmittedInfos.size());
 }
 
+// Constructs a comment definition as the parser would for one comment line.
+CommentInfo MakeOneLineCommentInfo(const std::string &Text) {
+  CommentInfo TopComment;
+  TopComment.Kind = "FullComment";
+  TopComment.Children.emplace_back(std::make_unique<CommentInfo>());
+
+  CommentInfo *Brief = TopComment.Children.back().get();
+  Brief->Kind = "ParagraphComment";
+
+  Brief->Children.emplace_back(std::make_unique<CommentInfo>());
+  Brief->Children.back()->Kind = "TextComment";
+  Brief->Children.back()->Name = "ParagraphComment";
+  Brief->Children.back()->Text = "Value of the thing.";
+
+  return TopComment;
+}
+
 // Test serialization of namespace declarations.
 TEST(SerializeTest, emitNamespaceInfo) {
   EmittedInfoList Infos;
@@ -124,6 +141,9 @@
   ExtractInfosFromCode(R"raw(class E {
 public:
   E() {}
+
+  // Some docs.
+  int value;
 protected:
   void ProtectedMethod();
 };
@@ -142,6 +162,9 @@
                                    InfoType::IT_namespace);
   ExpectedE.TagType = TagTypeKind::TTK_Class;
   ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
+  ExpectedE.Members.emplace_back("int", "value", AccessSpecifier::AS_public);
+  // TODO the data member should have the docstring on it:
+  //ExpectedE.Members.back().Description.push_back(MakeOneLineCommentInfo(" Some docs"));
   CheckRecordInfo(&ExpectedE, E);
 
   RecordInfo *RecordWithEConstructor = InfoAsRecord(Infos[2].get());
Index: clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp
===================================================================
--- clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp
+++ clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp
@@ -34,7 +34,12 @@
   return static_cast<EnumInfo *>(I);
 }
 
-void CheckCommentInfo(CommentInfo &Expected, CommentInfo &Actual) {
+void CheckCommentInfo(const std::vector<CommentInfo> &Expected,
+                      const std::vector<CommentInfo> &Actual);
+void CheckCommentInfo(const std::vector<std::unique_ptr<CommentInfo>> &Expected,
+                      const std::vector<std::unique_ptr<CommentInfo>> &Actual);
+
+void CheckCommentInfo(const CommentInfo &Expected, const CommentInfo &Actual) {
   EXPECT_EQ(Expected.Kind, Actual.Kind);
   EXPECT_EQ(Expected.Text, Actual.Text);
   EXPECT_EQ(Expected.Name, Actual.Name);
@@ -56,9 +61,21 @@
   for (size_t Idx = 0; Idx < Actual.Args.size(); ++Idx)
     EXPECT_EQ(Expected.Args[Idx], Actual.Args[Idx]);
 
-  ASSERT_EQ(Expected.Children.size(), Actual.Children.size());
-  for (size_t Idx = 0; Idx < Actual.Children.size(); ++Idx)
-    CheckCommentInfo(*Expected.Children[Idx], *Actual.Children[Idx]);
+  CheckCommentInfo(Expected.Children, Actual.Children);
+}
+
+void CheckCommentInfo(const std::vector<CommentInfo> &Expected,
+                      const std::vector<CommentInfo> &Actual) {
+  ASSERT_EQ(Expected.size(), Actual.size());
+  for (size_t Idx = 0; Idx < Actual.size(); ++Idx)
+    CheckCommentInfo(Expected[Idx], Actual[Idx]);
+}
+
+void CheckCommentInfo(const std::vector<std::unique_ptr<CommentInfo>> &Expected,
+                      const std::vector<std::unique_ptr<CommentInfo>> &Actual) {
+  ASSERT_EQ(Expected.size(), Actual.size());
+  for (size_t Idx = 0; Idx < Actual.size(); ++Idx)
+    CheckCommentInfo(*Expected[Idx], *Actual[Idx]);
 }
 
 void CheckReference(Reference &Expected, Reference &Actual) {
@@ -79,6 +96,7 @@
 void CheckMemberTypeInfo(MemberTypeInfo *Expected, MemberTypeInfo *Actual) {
   CheckFieldTypeInfo(Expected, Actual);
   EXPECT_EQ(Expected->Access, Actual->Access);
+  CheckCommentInfo(Expected->Description, Actual->Description);
 }
 
 void CheckBaseInfo(Info *Expected, Info *Actual) {
@@ -88,9 +106,7 @@
   ASSERT_EQ(Expected->Namespace.size(), Actual->Namespace.size());
   for (size_t Idx = 0; Idx < Actual->Namespace.size(); ++Idx)
     CheckReference(Expected->Namespace[Idx], Actual->Namespace[Idx]);
-  ASSERT_EQ(Expected->Description.size(), Actual->Description.size());
-  for (size_t Idx = 0; Idx < Actual->Description.size(); ++Idx)
-    CheckCommentInfo(Expected->Description[Idx], Actual->Description[Idx]);
+  CheckCommentInfo(Expected->Description, Actual->Description);
 }
 
 void CheckSymbolInfo(SymbolInfo *Expected, SymbolInfo *Actual) {
Index: clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp
===================================================================
--- clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp
+++ clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp
@@ -88,6 +88,18 @@
   I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record);
   I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
 
+  // Documentation for the data member.
+  CommentInfo TopComment;
+  TopComment.Kind = "FullComment";
+  TopComment.Children.emplace_back(std::make_unique<CommentInfo>());
+  CommentInfo *Brief = TopComment.Children.back().get();
+  Brief->Kind = "ParagraphComment";
+  Brief->Children.emplace_back(std::make_unique<CommentInfo>());
+  Brief->Children.back()->Kind = "TextComment";
+  Brief->Children.back()->Name = "ParagraphComment";
+  Brief->Children.back()->Text = "Value of the thing.";
+  I.Bases.back().Members.back().Description.emplace_back(std::move(TopComment));
+
   I.ChildRecords.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record);
   I.ChildFunctions.emplace_back();
   I.ChildEnums.emplace_back();
Index: clang-tools-extra/clang-doc/YAMLGenerator.cpp
===================================================================
--- clang-tools-extra/clang-doc/YAMLGenerator.cpp
+++ clang-tools-extra/clang-doc/YAMLGenerator.cpp
@@ -192,6 +192,7 @@
     // the AS that shouldn't be part of the output. Even though AS_public is the
     // default in the struct, it should be displayed in the YAML output.
     IO.mapOptional("Access", I.Access, clang::AccessSpecifier::AS_none);
+    IO.mapOptional("Description", I.Description);
   }
 };
 
Index: clang-tools-extra/clang-doc/Serialize.cpp
===================================================================
--- clang-tools-extra/clang-doc/Serialize.cpp
+++ clang-tools-extra/clang-doc/Serialize.cpp
@@ -29,6 +29,8 @@
 populateParentNamespaces(llvm::SmallVector<Reference, 4> &Namespaces,
                          const T *D, bool &IsAnonymousNamespace);
 
+static void populateMemberTypeInfo(MemberTypeInfo &I, const FieldDecl *D);
+
 // A function to extract the appropriate relative path for a given info's
 // documentation. The path returned is a composite of the parent namespaces.
 //
@@ -293,9 +295,11 @@
         continue;
       }
     }
-    I.Members.emplace_back(
+
+    auto& member = I.Members.emplace_back(
         F->getTypeSourceInfo()->getType().getAsString(), F->getNameAsString(),
         getFinalAccessSpecifier(Access, F->getAccessUnsafe()));
+    populateMemberTypeInfo(member, F);
   }
 }
 
@@ -431,6 +435,20 @@
   parseParameters(I, D);
 }
 
+static void populateMemberTypeInfo(MemberTypeInfo &I, const FieldDecl *D) {
+  assert(D);
+  ASTContext& Context = D->getASTContext();
+  RawComment *Comment = Context.getRawCommentForDeclNoCache(D);
+  if (!Comment)
+    return;
+
+  Comment->setAttached();
+  if (comments::FullComment* fc = Comment->parse(Context, nullptr, D)) {
+    I.Description.emplace_back();
+    parseFullComment(fc, I.Description.back());
+  }
+}
+
 static void
 parseBases(RecordInfo &I, const CXXRecordDecl *D, bool IsFileInRootDir,
            bool PublicOnly, bool IsParent,
Index: clang-tools-extra/clang-doc/Representation.h
===================================================================
--- clang-tools-extra/clang-doc/Representation.h
+++ clang-tools-extra/clang-doc/Representation.h
@@ -201,8 +201,8 @@
       : FieldTypeInfo(RefName, Path, Name), Access(Access) {}
 
   bool operator==(const MemberTypeInfo &Other) const {
-    return std::tie(Type, Name, Access) ==
-           std::tie(Other.Type, Other.Name, Other.Access);
+    return std::tie(Type, Name, Access, Description) ==
+           std::tie(Other.Type, Other.Name, Other.Access, Other.Description);
   }
 
   // Access level associated with this info (public, protected, private, none).
@@ -210,6 +210,8 @@
   // with value 0 to be used as the default.
   // (AS_public = 0, AS_protected = 1, AS_private = 2, AS_none = 3)
   AccessSpecifier Access = AccessSpecifier::AS_public;
+
+  std::vector<CommentInfo> Description; // Comment description of this field.
 };
 
 struct Location {
Index: clang-tools-extra/clang-doc/BitcodeWriter.cpp
===================================================================
--- clang-tools-extra/clang-doc/BitcodeWriter.cpp
+++ clang-tools-extra/clang-doc/BitcodeWriter.cpp
@@ -426,6 +426,8 @@
   emitBlock(T.Type, FieldId::F_type);
   emitRecord(T.Name, MEMBER_TYPE_NAME);
   emitRecord(T.Access, MEMBER_TYPE_ACCESS);
+  for (const auto &CI : T.Description)
+    emitBlock(CI);
 }
 
 void ClangDocBitcodeWriter::emitBlock(const CommentInfo &I) {
Index: clang-tools-extra/clang-doc/BitcodeReader.cpp
===================================================================
--- clang-tools-extra/clang-doc/BitcodeReader.cpp
+++ clang-tools-extra/clang-doc/BitcodeReader.cpp
@@ -350,6 +350,11 @@
   return &I->Description.back();
 }
 
+template <> llvm::Expected<CommentInfo *> getCommentInfo(MemberTypeInfo *I) {
+  I->Description.emplace_back();
+  return &I->Description.back();
+}
+
 template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumInfo *I) {
   I->Description.emplace_back();
   return &I->Description.back();
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to