[PATCH] D11069: Allow any comment to be a trailing comment when -fparse-all-comments is on.

Luke Zarko zarko at google.com
Thu Jul 9 10:50:26 PDT 2015


zarko created this revision.
zarko added a subscriber: cfe-commits.

This helps with freeform documentation styles, where otherwise code like

```
  enum class E {
    E1,  // D1
    E2   // D2
  };
```

would result in D1 being associated with E2. To properly associate E1
with D1 and E2 with D2, this patch allows all raw comments C such that
C.isParseAllComments() to participate in trailing comment checks inside
getRawCommentForDeclNoCache. This takes care of linking the intended
documentation with the intended decls. There remains an issue with code
like:

```
  foo();  // DN
  int x;
```

To prevent DN from being associated with x, this patch adds a new test
on preceding-line comments C (where C.isParseAllComments() and also
C's kind is RCK_OrdinaryBCPL or RCK_OrdinaryC) that checks whether C
is the first non-whitespace thing on C's starting line.

http://reviews.llvm.org/D11069

Files:
  lib/AST/ASTContext.cpp
  test/Index/parse-all-comments.c

Index: test/Index/parse-all-comments.c
===================================================================
--- test/Index/parse-all-comments.c
+++ test/Index/parse-all-comments.c
@@ -33,6 +33,9 @@
 // WITH EMPTY LINE
 void multi_line_comment_empty_line(int);
 
+int notdoxy7; // Not a Doxygen juxtaposed comment.  notdoxy7 NOT_DOXYGEN
+int notdoxy8; // Not a Doxygen juxtaposed comment.  notdoxy8 NOT_DOXYGEN
+
 #endif
 
 // RUN: rm -rf %t
@@ -60,3 +63,5 @@
 // CHECK: parse-all-comments.c:22:6: FunctionDecl=isdoxy6:{{.*}} isdoxy6 IS_DOXYGEN_SINGLE
 // CHECK: parse-all-comments.c:29:6: FunctionDecl=multi_line_comment_plus_ordinary:{{.*}} BLOCK_ORDINARY_COMMENT {{.*}} ORDINARY COMMENT {{.*}} IS_DOXYGEN_START {{.*}} IS_DOXYGEN_END
 // CHECK: parse-all-comments.c:34:6: FunctionDecl=multi_line_comment_empty_line:{{.*}} MULTILINE COMMENT{{.*}}\n{{.*}}\n{{.*}} WITH EMPTY LINE
+// CHECK: parse-all-comments.c:36:5: VarDecl=notdoxy7:{{.*}} notdoxy7 NOT_DOXYGEN
+// CHECK: parse-all-comments.c:37:5: VarDecl=notdoxy8:{{.*}} notdoxy8 NOT_DOXYGEN
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -60,6 +60,33 @@
   HalfRank, FloatRank, DoubleRank, LongDoubleRank
 };
 
+/// \brief Determines whether there is only whitespace in `Buffer` between `P`
+/// and the previous line.
+/// \param Buffer The buffer to search in.
+/// \param P The offset from the beginning of `Buffer` to start from.
+/// \return true if all of the characters in `Buffer` ranging from the closest
+/// line-ending character before `P` (or the beginning of `Buffer`) to `P - 1`
+/// are whitespace.
+static bool OnlyWhitespaceOnLineBefore(const char *Buffer, unsigned P) {
+  // Search backwards until we see linefeed or carriage return.
+  for (unsigned I = P; I != 0; --I) {
+    switch (Buffer[I - 1]) {
+    default:
+      return false;
+    case ' ':
+    case '\t':
+    case '\f':
+    case '\v':
+      break;
+    case '\r':
+    case '\n':
+      return true;
+    }
+  }
+  // We hit the beginning of the buffer.
+  return true;
+}
+
 RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const {
   if (!CommentsLoaded && ExternalSource) {
     ExternalSource->ReadComments();
@@ -203,7 +230,8 @@
 
   // First check whether we have a trailing comment.
   if (Comment != RawComments.end() &&
-      (*Comment)->isDocumentation() && (*Comment)->isTrailingComment() &&
+      ((*Comment)->isParseAllComments() ||
+       ((*Comment)->isDocumentation() && (*Comment)->isTrailingComment())) &&
       (isa<FieldDecl>(D) || isa<EnumConstantDecl>(D) || isa<VarDecl>(D) ||
        isa<ObjCMethodDecl>(D) || isa<ObjCPropertyDecl>(D))) {
     std::pair<FileID, unsigned> CommentBeginDecomp
@@ -224,6 +252,27 @@
     return nullptr;
   --Comment;
 
+  if ((*Comment)->isParseAllComments() &&
+      ((*Comment)->getKind() == RawComment::RCK_OrdinaryBCPL ||
+       (*Comment)->getKind() == RawComment::RCK_OrdinaryC)) {
+    // When we're trying to guess which comments are actually documentation
+    // comments and the previous comment was ordinary, assume that it's
+    // unrelated if it's not the first thing on its starting line. This may
+    // be a comment unrelated to anything, or it might be a trailing comment
+    // for a different Decl.
+    std::pair<FileID, unsigned> CommentBeginDecomp =
+        SourceMgr.getDecomposedLoc((*Comment)->getSourceRange().getBegin());
+    if (CommentBeginDecomp.second != 0) {
+      // We're spuriously OK if this was the first thing in the file.
+      bool Invalid = false;
+      const char *Buffer =
+          SourceMgr.getBufferData(CommentBeginDecomp.first, &Invalid).data();
+      if (Invalid ||
+          !OnlyWhitespaceOnLineBefore(Buffer, CommentBeginDecomp.second))
+        return nullptr;
+    }
+  }
+
   // Check that we actually have a non-member Doxygen comment.
   if (!(*Comment)->isDocumentation() || (*Comment)->isTrailingComment())
     return nullptr;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D11069.29357.patch
Type: text/x-patch
Size: 4025 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150709/c6af569c/attachment.bin>


More information about the cfe-commits mailing list