Repository: eslint/doctrine (js)

Issue:
default param value of " " is trimmed to an empty string ""
In the [doctrine demo](http://eslint.org/doctrine/demo/) try:
```
     * @param {string} [chars='     '] Foo.
```
Then in the dev console of the demo:
```js
var result = doctrine.parse($('#code').val(), { sloppy: true, unwrap: true });
```
You'll see the `result.tags[0]['default']` is `"''"` instead of `"'   '"`.

Pull request description:
Fix: Preserve whitespace in default param string values (fixes #157)

Patch:
diff --git a/lib/doctrine.js b/lib/doctrine.js
index f82331d..d04c43c 100644
--- a/lib/doctrine.js
+++ b/lib/doctrine.js
@@ -299,7 +299,9 @@
         }
 
         function parseName(last, allowBrackets, allowNestedParams) {
-            var name = '', useBrackets;
+            var name = '',
+                useBrackets,
+                insideString;
 
             skipWhiteSpace(last);
 
@@ -351,13 +353,36 @@
 
                     var ch;
                     var bracketDepth = 1;
+
                     // scan in the default value
                     while (index < last) {
                         ch = source.charCodeAt(index);
 
                         if (esutils.code.isWhiteSpace(ch)) {
-                            skipWhiteSpace(last);
-                            ch = source.charCodeAt(index);
+                            if (!insideString) {
+                                skipWhiteSpace(last);
+                                ch = source.charCodeAt(index);
+                            }
+                        }
+
+                        if (ch === 0x27 /* ''' */) {
+                            if (!insideString) {
+                                insideString = '\'';
+                            } else {
+                                if (insideString === '\'') {
+                                    insideString = '';
+                                }
+                            }
+                        }
+
+                        if (ch === 0x22 /* '"' */) {
+                            if (!insideString) {
+                                insideString = '"';
+                            } else {
+                                if (insideString === '"') {
+                                    insideString = '';
+                                }
+                            }
                         }
 
                         if (ch === 0x5B /* '[' */) {
@@ -373,7 +398,7 @@
 
                 skipWhiteSpace(last);
 
-                if (index >= last  || source.charCodeAt(index) !== 0x5D  /* ']' */) {
+                if (index >= last || source.charCodeAt(index) !== 0x5D  /* ']' */) {
                     // we never found a closing ']'
                     return null;
                 }


Test patch:
diff --git a/test/parse.js b/test/parse.js
index 9a45f8d..6bd744d 100644
--- a/test/parse.js
+++ b/test/parse.js
@@ -2004,6 +2004,72 @@ describe('optional params', function() {
         });
     });
 
+    it('default string', function() {
+        doctrine.parse(
+            ["/**", " * @param {String} [val=\"foo\"] some description", " */"].join('\n'),
+            { unwrap: true, sloppy: true}
+        ).should.eql({
+            "description": "",
+            "tags": [{
+                "title": "param",
+                "description": "some description",
+                "type": {
+                    "type": "OptionalType",
+                    "expression": {
+                        "type": "NameExpression",
+                        "name": "String"
+                    }
+                },
+                "name": "val",
+                "default": "\"foo\""
+            }]
+        });
+    });
+
+    it('default string surrounded by whitespace', function() {
+        doctrine.parse(
+            ["/**", " * @param {String} [val=   'foo'  ] some description", " */"].join('\n'),
+            { unwrap: true, sloppy: true}
+        ).should.eql({
+            "description": "",
+            "tags": [{
+                "title": "param",
+                "description": "some description",
+                "type": {
+                    "type": "OptionalType",
+                    "expression": {
+                        "type": "NameExpression",
+                        "name": "String"
+                    }
+                },
+                "name": "val",
+                "default": "'foo'"
+            }]
+        });
+    });
+
+    it('should preserve whitespace in default string', function() {
+        doctrine.parse(
+            ["/**", " * @param {String} [val=   \"   foo\"  ] some description", " */"].join('\n'),
+            { unwrap: true, sloppy: true}
+        ).should.eql({
+            "description": "",
+            "tags": [{
+                "title": "param",
+                "description": "some description",
+                "type": {
+                    "type": "OptionalType",
+                    "expression": {
+                        "type": "NameExpression",
+                        "name": "String"
+                    }
+                },
+                "name": "val",
+                "default": "\"   foo\""
+            }]
+        });
+    });
+
     it('default array', function() {
         doctrine.parse(
             ["/**", " * @param {String} [val=['foo']] some description", " */"].join('\n'),
@@ -2026,6 +2092,27 @@ describe('optional params', function() {
         });
     });
 
+    it('default array', function() {
+        doctrine.parse(
+            ["/**", " * @param {String} [val=['foo']] some description", " */"].join('\n'),
+            { unwrap: true, sloppy: true}
+        ).should.eql({
+            "description": "",
+            "tags": [{
+                "title": "param",
+                "description": "some description",
+                "type": {
+                    "type": "OptionalType",
+                    "expression": {
+                        "type": "NameExpression",
+                        "name": "String"
+                    }
+                },
+                "name": "val",
+                "default": "['foo']"
+            }]
+        });
+    });
 
     it('default array within white spaces', function() {
         doctrine.parse(