| 1 | if (typeof JSDOC == "undefined") JSDOC = {}; |
| 2 | |
| 3 | /** |
| 4 | Create a new DocComment. This takes a raw documentation comment, |
| 5 | and wraps it in useful accessors. |
| 6 | @class Represents a documentation comment object. |
| 7 | */ |
| 8 | JSDOC.DocComment = function(/**String*/comment) { |
| 9 | this.init(); |
| 10 | if (typeof comment != "undefined") { |
| 11 | this.parse(comment); |
| 12 | } |
| 13 | } |
| 14 | |
| 15 | JSDOC.DocComment.prototype.init = function() { |
| 16 | this.isUserComment = true; |
| 17 | this.src = ""; |
| 18 | this.meta = ""; |
| 19 | this.tagTexts = []; |
| 20 | this.tags = []; |
| 21 | } |
| 22 | |
| 23 | /** |
| 24 | @requires JSDOC.DocTag |
| 25 | */ |
| 26 | JSDOC.DocComment.prototype.parse = function(/**String*/comment) { |
| 27 | if (comment == "") { |
| 28 | comment = "/** @desc */"; |
| 29 | this.isUserComment = false; |
| 30 | } |
| 31 | |
| 32 | this.src = JSDOC.DocComment.unwrapComment(comment); |
| 33 | |
| 34 | this.meta = ""; |
| 35 | if (this.src.indexOf("#") == 0) { |
| 36 | this.src.match(/#(.+[+-])([\s\S]*)$/); |
| 37 | if (RegExp.$1) this.meta = RegExp.$1; |
| 38 | if (RegExp.$2) this.src = RegExp.$2; |
| 39 | } |
| 40 | |
| 41 | if (typeof JSDOC.PluginManager != "undefined") { |
| 42 | JSDOC.PluginManager.run("onDocCommentSrc", this); |
| 43 | } |
| 44 | |
| 45 | this.fixDesc(); |
| 46 | |
| 47 | this.src = JSDOC.DocComment.shared+"\n"+this.src; |
| 48 | |
| 49 | this.tagTexts = |
| 50 | this.src |
| 51 | .split(/(^|[\r\n])\s*@/) |
| 52 | .filter(function($){return $.match(/\S/)}); |
| 53 | |
| 54 | /** |
| 55 | The tags found in the comment. |
| 56 | @type JSDOC.DocTag[] |
| 57 | */ |
| 58 | this.tags = this.tagTexts.map(function($){return new JSDOC.DocTag($)}); |
| 59 | |
| 60 | if (typeof JSDOC.PluginManager != "undefined") { |
| 61 | JSDOC.PluginManager.run("onDocCommentTags", this); |
| 62 | } |
| 63 | } |
| 64 | |
| 65 | /*t: |
| 66 | plan(5, "testing JSDOC.DocComment"); |
| 67 | requires("../frame/String.js"); |
| 68 | requires("../lib/JSDOC/DocTag.js"); |
| 69 | |
| 70 | var com = new JSDOC.DocComment("/**@foo some\n* comment here*"+"/"); |
| 71 | is(com.tagTexts[0], "foo some\ncomment here", "first tag text is found."); |
| 72 | is(com.tags[0].title, "foo", "the title is found in a comment with one tag."); |
| 73 | |
| 74 | var com = new JSDOC.DocComment("/** @foo first\n* @bar second*"+"/"); |
| 75 | is(com.getTag("bar").length, 1, "getTag() returns one tag by that title."); |
| 76 | |
| 77 | JSDOC.DocComment.shared = "@author John Smith"; |
| 78 | var com = new JSDOC.DocComment("/**@foo some\n* comment here*"+"/"); |
| 79 | is(com.tags[0].title, "author", "shared comment is added."); |
| 80 | is(com.tags[1].title, "foo", "shared comment is added to existing tag."); |
| 81 | */ |
| 82 | |
| 83 | /** |
| 84 | If no @desc tag is provided, this function will add it. |
| 85 | */ |
| 86 | JSDOC.DocComment.prototype.fixDesc = function() { |
| 87 | if (this.meta && this.meta != "@+") return; |
| 88 | if (/^\s*[^@\s]/.test(this.src)) { |
| 89 | this.src = "@desc "+this.src; |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | /*t: |
| 94 | plan(5, "testing JSDOC.DocComment#fixDesc"); |
| 95 | |
| 96 | var com = new JSDOC.DocComment(); |
| 97 | |
| 98 | com.src = "this is a desc\n@author foo"; |
| 99 | com.fixDesc(); |
| 100 | is(com.src, "@desc this is a desc\n@author foo", "if no @desc tag is provided one is added."); |
| 101 | |
| 102 | com.src = "x"; |
| 103 | com.fixDesc(); |
| 104 | is(com.src, "@desc x", "if no @desc tag is provided one is added to a single character."); |
| 105 | |
| 106 | com.src = "\nx"; |
| 107 | com.fixDesc(); |
| 108 | is(com.src, "@desc \nx", "if no @desc tag is provided one is added to return and character."); |
| 109 | |
| 110 | com.src = " "; |
| 111 | com.fixDesc(); |
| 112 | is(com.src, " ", "if no @desc tag is provided one is not added to just whitespace."); |
| 113 | |
| 114 | com.src = ""; |
| 115 | com.fixDesc(); |
| 116 | is(com.src, "", "if no @desc tag is provided one is not added to empty."); |
| 117 | */ |
| 118 | |
| 119 | /** |
| 120 | Remove slash-star comment wrapper from a raw comment string. |
| 121 | @type String |
| 122 | */ |
| 123 | JSDOC.DocComment.unwrapComment = function(/**String*/comment) { |
| 124 | if (!comment) return ""; |
| 125 | var unwrapped = comment.replace(/(^\/\*\*|\*\/$)/g, "").replace(/^\s*\* ?/gm, ""); |
| 126 | return unwrapped; |
| 127 | } |
| 128 | |
| 129 | /*t: |
| 130 | plan(5, "testing JSDOC.DocComment.unwrapComment"); |
| 131 | |
| 132 | var com = "/**x*"+"/"; |
| 133 | var unwrapped = JSDOC.DocComment.unwrapComment(com); |
| 134 | is(unwrapped, "x", "a single character jsdoc is found."); |
| 135 | |
| 136 | com = "/***x*"+"/"; |
| 137 | unwrapped = JSDOC.DocComment.unwrapComment(com); |
| 138 | is(unwrapped, "x", "three stars are allowed in the opener."); |
| 139 | |
| 140 | com = "/****x*"+"/"; |
| 141 | unwrapped = JSDOC.DocComment.unwrapComment(com); |
| 142 | is(unwrapped, "*x", "fourth star in the opener is kept."); |
| 143 | |
| 144 | com = "/**x\n * y\n*"+"/"; |
| 145 | unwrapped = JSDOC.DocComment.unwrapComment(com); |
| 146 | is(unwrapped, "x\ny\n", "leading stars and spaces are trimmed."); |
| 147 | |
| 148 | com = "/**x\n * y\n*"+"/"; |
| 149 | unwrapped = JSDOC.DocComment.unwrapComment(com); |
| 150 | is(unwrapped, "x\n y\n", "only first space after leading stars are trimmed."); |
| 151 | */ |
| 152 | |
| 153 | /** |
| 154 | Provides a printable version of the comment. |
| 155 | @type String |
| 156 | */ |
| 157 | JSDOC.DocComment.prototype.toString = function() { |
| 158 | return this.src; |
| 159 | } |
| 160 | |
| 161 | /*t: |
| 162 | plan(1, "testing JSDOC.DocComment#fixDesc"); |
| 163 | var com = new JSDOC.DocComment(); |
| 164 | com.src = "foo"; |
| 165 | is(""+com, "foo", "stringifying a comment returns the unwrapped src."); |
| 166 | */ |
| 167 | |
| 168 | /** |
| 169 | Given the title of a tag, returns all tags that have that title. |
| 170 | @type JSDOC.DocTag[] |
| 171 | */ |
| 172 | JSDOC.DocComment.prototype.getTag = function(/**String*/tagTitle) { |
| 173 | return this.tags.filter(function($){return $.title == tagTitle}); |
| 174 | } |
| 175 | |
| 176 | JSDOC.DocComment.prototype.deleteTag = function(/**String*/tagTitle) { |
| 177 | this.tags = this.tags.filter(function($){return $.title != tagTitle}) |
| 178 | } |
| 179 | |
| 180 | /*t: |
| 181 | plan(1, "testing JSDOC.DocComment#getTag"); |
| 182 | requires("../frame/String.js"); |
| 183 | requires("../lib/JSDOC/DocTag.js"); |
| 184 | |
| 185 | var com = new JSDOC.DocComment("/**@foo some\n* @bar\n* @bar*"+"/"); |
| 186 | is(com.getTag("bar").length, 2, "getTag returns expected number of tags."); |
| 187 | */ |
| 188 | |
| 189 | /** |
| 190 | Used to store the currently shared tag text. |
| 191 | */ |
| 192 | JSDOC.DocComment.shared = ""; |
| 193 | |
| 194 | /*t: |
| 195 | plan(2, "testing JSDOC.DocComment.shared"); |
| 196 | requires("../frame/String.js"); |
| 197 | requires("../lib/JSDOC/DocTag.js"); |
| 198 | |
| 199 | JSDOC.DocComment.shared = "@author Michael"; |
| 200 | |
| 201 | var com = new JSDOC.DocComment("/**@foo\n* @foo*"+"/"); |
| 202 | is(com.getTag("author").length, 1, "getTag returns shared tag."); |
| 203 | is(com.getTag("foo").length, 2, "getTag returns unshared tags too."); |
| 204 | */ |