diff trunk/src/dil/doc/Doc.d @ 785:57ef69eced96

Added functions isCodeSection() and skipCodeSection(). Added a lot of documentation comments and revised some.
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Sat, 23 Feb 2008 21:15:56 +0100
parents 939097e0990f
children 3b34f6a95a27
line wrap: on
line diff
--- a/trunk/src/dil/doc/Doc.d	Sat Feb 23 02:26:43 2008 +0100
+++ b/trunk/src/dil/doc/Doc.d	Sat Feb 23 21:15:56 2008 +0100
@@ -12,6 +12,7 @@
 
 import tango.text.Ascii : icompare;
 
+/// Represents a sanitized and parsed DDoc comment.
 class DDocComment
 {
   Section[] sections; /// The sections of this comment.
@@ -37,7 +38,7 @@
     return null;
   }
 
-  /// Returns: true if "ditto" is the only text in this comment.
+  /// Returns true if "ditto" is the only text in this comment.
   bool isDitto()
   {
     if (summary && sections.length == 1 &&
@@ -45,15 +46,6 @@
       return true;
     return false;
   }
-
-//   MacrosSection[] getMacros()
-//   {
-//     MacrosSection[] macros;
-//     foreach (section; sections)
-//       if (section.Is("macros"))
-//         macros ~= new MacrosSection(section.name, section.text);
-//     return macros;
-//   }
 }
 
 /// Returns a node's DDocComment.
@@ -90,8 +82,8 @@
 /// Parses a DDoc comment string.
 struct DDocParser
 {
-  char* p;
-  char* textEnd;
+  char* p; /// Current character pointer.
+  char* textEnd; /// Points one character past the end of the text.
   Section[] sections; /// Parsed sections.
   Section summary; /// Optional summary section.
   Section description; /// Optional description section.
@@ -151,6 +143,8 @@
     return makeString(begin, end);
   }
 
+  /// Separates the text between p and end
+  /// into a summary and description section.
   void scanSummaryAndDescription(char* p, char* end)
   {
     assert(p <= end);
@@ -159,18 +153,8 @@
     end--; // Decrement end, so we can look ahead one character.
     while (p < end && !(*p == '\n' && p[1] == '\n'))
     {
-      // Skip over code sections. This is unlike how dmd behaves.
-      if (p+2 < end && *p == '-' && p[1] == '-' && p[2] == '-')
-      {
-        while (p < end && *p == '-')
-          p++;
-        p--;
-        while (++p < end)
-          if (p+2 < end && *p == '-' && p[1] == '-' && p[2] == '-')
-            break;
-        if (p >= end)
-          break;
-      }
+      if (isCodeSection(p, end))
+        skipCodeSection(p, end);
       p++;
     }
     end++;
@@ -193,6 +177,34 @@
     }
   }
 
+  /// Returns true if p points to "$(DDD)".
+  bool isCodeSection(char* p, char* end)
+  {
+    return p+2 < end && *p == '-' && p[1] == '-' && p[2] == '-';
+  }
+
+  /// Skips over a code section.
+  ///
+  /// Note that dmd apparently doesn't skip over code sections when
+  /// parsing DDoc sections. However, from experience it seems
+  /// to be a good idea to do that.
+  void skipCodeSection(ref char* p, char* end)
+  out { assert(p+1 == end || *p == '-'); }
+  body
+  {
+    assert(isCodeSection(p, end));
+
+    while (p < end && *p == '-')
+      p++;
+    p--;
+    while (++p < end)
+      if (p+2 < end && *p == '-' && p[1] == '-' && p[2] == '-')
+        break;
+    while (p < end && *p == '-')
+      p++;
+    p--;
+  }
+
   void skipWhitespace(ref char* p)
   {
     while (p < textEnd && (isspace(*p) || *p == '\n'))
@@ -201,7 +213,7 @@
 
   /// Find next "Identifier:".
   /// Params:
-  ///   ident = set to the Identifier
+  ///   ident = set to the Identifier.
   ///   bodyBegin = set to the beginning of the text body (whitespace skipped.)
   /// Returns: true if found.
   bool findNextIdColon(ref char[] ident, ref char* bodyBegin)
@@ -211,6 +223,12 @@
       skipWhitespace(p);
       if (p >= textEnd)
         break;
+      if (isCodeSection(p, textEnd))
+      {
+        skipCodeSection(p, textEnd);
+        p++;
+        continue;
+      }
       assert(isascii(*p) || isLeadByte(*p));
       auto idBegin = p;
       if (isidbeg(*p) || isUnicodeAlpha(p, textEnd)) // IdStart
@@ -236,6 +254,7 @@
   }
 }
 
+/// Represents a DDoc section.
 class Section
 {
   string name;
@@ -246,6 +265,7 @@
     this.text = text;
   }
 
+  /// Case-insensitively compares the section's name with name2.
   bool Is(char[] name2)
   {
     return icompare(name, name2) == 0;
@@ -290,21 +310,24 @@
   }
 }
 
+/// Returns true if token is a Doxygen comment.
 bool isDoxygenComment(Token* token)
 { // Doxygen: '/+!' '/*!' '//!'
   return token.kind == TOK.Comment && token.start[2] == '!';
 }
 
+/// Returns true if token is a DDoc comment.
 bool isDDocComment(Token* token)
 { // DDOC: '/++' '/**' '///'
   return token.kind == TOK.Comment && token.start[1] == token.start[2];
 }
 
-/++
-  Returns the surrounding documentation comment tokens.
-  Note: this function works correctly only if
-        the source text is syntactically correct.
-+/
+/// Returns the surrounding documentation comment tokens.
+/// Params:
+///   node = the node to find doc comments for.
+///   isDocComment = a function predicate that checks for doc comment tokens.
+/// Note: this function works correctly only if
+///       the source text is syntactically correct.
 Token*[] getDocTokens(Node node, bool function(Token*) isDocComment = &isDDocComment)
 {
   Token*[] comments;
@@ -313,13 +336,12 @@
   auto token = node.begin;
   // Scan backwards until we hit another declaration.
 Loop:
-  while (1)
+  for (; token; token = token.prev)
   {
-    token = token.prev;
     if (token.kind == TOK.LBrace ||
         token.kind == TOK.RBrace ||
         token.kind == TOK.Semicolon ||
-        token.kind == TOK.HEAD ||
+        /+token.kind == TOK.HEAD ||+/
         (isEnumMember && token.kind == TOK.Comma))
       break;
 
@@ -379,6 +401,7 @@
 }
 
 /// Sanitizes a DDoc comment string.
+///
 /// Leading "commentChar"s are removed from the lines.
 /// The various newline types are converted to '\n'.
 /// Params: