From 8ea16e11973638ad0aafa9681997fade9305bcff Mon Sep 17 00:00:00 2001
From: "rdevlin.cronin" <rdevlin.cronin@chromium.org>
Date: Thu, 26 Mar 2015 17:13:13 -0700
Subject: [Extension API Extern Generation] Fix comment indentation

For extern comments, line wrapping sometimes has indentation. For instance:
/**
 * @param {FooBar} This is some foobar
 *     that has the comment wrapped.
 */
We should support this.  Add an optional parameter to the Code Comment method
to allow for comment indentation.

BUG=461039

Review URL: https://codereview.chromium.org/1010603007

Cr-Commit-Position: refs/heads/master@{#322504}
---
 tools/json_schema_compiler/code.py                 | 30 ++++++++++++++++------
 tools/json_schema_compiler/code_test.py            | 30 ++++++++++++++--------
 tools/json_schema_compiler/js_externs_generator.py |  7 ++---
 .../js_externs_generator_test.py                   |  7 ++++-
 4 files changed, 51 insertions(+), 23 deletions(-)

(limited to 'tools/json_schema_compiler')

diff --git a/tools/json_schema_compiler/code.py b/tools/json_schema_compiler/code.py
index 8ce6afa..10a5d88 100644
--- a/tools/json_schema_compiler/code.py
+++ b/tools/json_schema_compiler/code.py
@@ -85,7 +85,7 @@ class Code(object):
       self.Append(line)
     return self
 
-  def Comment(self, comment, comment_prefix='// '):
+  def Comment(self, comment, comment_prefix='// ', wrap_indent=0):
     """Adds the given string as a comment.
 
     Will split the comment if it's too long. Use mainly for variable length
@@ -93,17 +93,31 @@ class Code(object):
 
     Unaffected by code.Substitute().
     """
-    max_len = self._comment_length - self._indent_level - len(comment_prefix)
-    while len(comment) >= max_len:
-      line = comment[0:max_len]
-      last_space = line.rfind(' ')
+    # Helper function to trim a comment to the maximum length, and return one
+    # line and the remainder of the comment.
+    def trim_comment(comment, max_len):
+      if len(comment) <= max_len:
+        return comment, ''
+      last_space = comment.rfind(' ', 0, max_len + 1)
       if last_space != -1:
-        line = line[0:last_space]
+        line = comment[0:last_space]
         comment = comment[last_space + 1:]
       else:
+        line = comment[0:max_len]
         comment = comment[max_len:]
-      self.Append(comment_prefix + line, substitute=False)
-    self.Append(comment_prefix + comment, substitute=False)
+      return line, comment
+
+    # First line has the full maximum length.
+    max_len = self._comment_length - self._indent_level - len(comment_prefix)
+    line, comment = trim_comment(comment, max_len)
+    self.Append(comment_prefix + line, substitute=False)
+
+    # Any subsequent lines be subject to the wrap indent.
+    max_len = max_len - wrap_indent
+    while len(comment):
+      line, comment = trim_comment(comment, max_len)
+      self.Append(comment_prefix + (' ' * wrap_indent) + line, substitute=False)
+
     return self
 
   def Substitute(self, d):
diff --git a/tools/json_schema_compiler/code_test.py b/tools/json_schema_compiler/code_test.py
index ca36524..c6ca33f 100755
--- a/tools/json_schema_compiler/code_test.py
+++ b/tools/json_schema_compiler/code_test.py
@@ -117,14 +117,14 @@ class CodeTest(unittest.TestCase):
     self.assertFalse(c.IsEmpty())
 
   def testComment(self):
-    long_comment = ('This comment is eighty nine characters in longness, '
-        'that is, to use another word, length')
+    long_comment = ('This comment is ninety one characters in longness, '
+        'that is, using a different word, length.')
     c = Code()
     c.Comment(long_comment)
     self.assertEquals(
-        '// This comment is eighty nine characters '
-        'in longness, that is, to use another\n'
-        '// word, length',
+        '// This comment is ninety one characters '
+        'in longness, that is, using a different\n'
+        '// word, length.',
         c.Render())
     c = Code()
     c.Sblock('sblock')
@@ -133,13 +133,13 @@ class CodeTest(unittest.TestCase):
     c.Comment(long_comment)
     self.assertEquals(
         'sblock\n'
-        '  // This comment is eighty nine characters '
-        'in longness, that is, to use\n'
-        '  // another word, length\n'
+        '  // This comment is ninety one characters '
+        'in longness, that is, using a\n'
+        '  // different word, length.\n'
         'eblock\n'
-        '// This comment is eighty nine characters in '
-        'longness, that is, to use another\n'
-        '// word, length',
+        '// This comment is ninety one characters in '
+        'longness, that is, using a different\n'
+        '// word, length.',
         c.Render())
     long_word = 'x' * 100
     c = Code()
@@ -148,6 +148,14 @@ class CodeTest(unittest.TestCase):
         '// ' + 'x' * 77 + '\n'
         '// ' + 'x' * 23,
         c.Render())
+    c = Code(indent_size=2, comment_length=40)
+    c.Comment('Pretend this is a Closure Compiler style comment, which should '
+        'both wrap and indent', comment_prefix=' * ', wrap_indent=4)
+    self.assertEquals(
+        ' * Pretend this is a Closure Compiler\n'
+        ' *     style comment, which should both\n'
+        ' *     wrap and indent',
+        c.Render())
 
   def testCommentWithSpecialCharacters(self):
     c = Code()
diff --git a/tools/json_schema_compiler/js_externs_generator.py b/tools/json_schema_compiler/js_externs_generator.py
index 8512ac4..587c04e 100644
--- a/tools/json_schema_compiler/js_externs_generator.py
+++ b/tools/json_schema_compiler/js_externs_generator.py
@@ -94,7 +94,7 @@ class _Generator(object):
 
     is_constructor = self._IsTypeConstructor(js_type)
     if is_constructor:
-      c.Comment('@constructor', comment_prefix = ' * ')
+      c.Comment('@constructor', comment_prefix = ' * ', wrap_indent=4)
     else:
       c.Concat(self._GenerateTypedef(js_type.properties))
 
@@ -141,7 +141,8 @@ class _Generator(object):
 
     lines = []
     if function.description:
-      lines.extend(function.description.splitlines())
+      for line in function.description.splitlines():
+        c.Comment(line, comment_prefix=' * ')
 
     for param in function.params:
       js_type = self._TypeToJsType(param.type_)
@@ -165,7 +166,7 @@ class _Generator(object):
       lines.append('@deprecated %s' % function.deprecated)
 
     for line in lines:
-      c.Comment(line, comment_prefix=' * ');
+      c.Comment(line, comment_prefix=' * ', wrap_indent=4);
 
     c.Append(' */')
     return c
diff --git a/tools/json_schema_compiler/js_externs_generator_test.py b/tools/json_schema_compiler/js_externs_generator_test.py
index 0d4160b..2ca3169 100755
--- a/tools/json_schema_compiler/js_externs_generator_test.py
+++ b/tools/json_schema_compiler/js_externs_generator_test.py
@@ -54,6 +54,9 @@ namespace fakeApi {
     // |baz| : The baz to use.
     static void doSomething(Baz baz, VoidCallback callback);
 
+    // |callback| : The callback which will most assuredly in all cases be
+    // called; that is, of course, iff such a callback was provided and is
+    // not at all null.
     static void bazGreek(optional BazGreekCallback callback);
 
     [deprecated="Use a new method."] static DOMString returnString();
@@ -117,7 +120,9 @@ var Baz;
 chrome.fakeApi.doSomething = function(baz, callback) {};
 
 /**
- * @param {function(Baz, !chrome.fakeApi.Greek):void=} callback
+ * @param {function(Baz, !chrome.fakeApi.Greek):void=} callback The callback
+ *     which will most assuredly in all cases be called; that is, of course, iff
+ *     such a callback was provided and is not at all null.
  */
 chrome.fakeApi.bazGreek = function(callback) {};
 
-- 
cgit v1.1