can generate jsdoc; private methods marked as such
[dygraphs.git] / jsdoc-toolkit / app / lib / JSDOC / DocTag.js
CommitLineData
629a09ae
DV
1if (typeof JSDOC == "undefined") JSDOC = {};
2
3/**
4 @constructor
5 */
6JSDOC.DocTag = function(src) {
7 this.init();
8 if (typeof src != "undefined") {
9 this.parse(src);
10 }
11}
12
13/**
14 Create and initialize the properties of this.
15 */
16JSDOC.DocTag.prototype.init = function() {
17 this.title = "";
18 this.type = "";
19 this.name = "";
20 this.isOptional = false;
21 this.defaultValue = "";
22 this.desc = "";
23
24 return this;
25}
26
27/**
28 Populate the properties of this from the given tag src.
29 @param {string} src
30 */
31JSDOC.DocTag.prototype.parse = function(src) {
32 if (typeof src != "string") throw "src must be a string not "+(typeof src);
33
34 try {
35 src = this.nibbleTitle(src);
36 if (JSDOC.PluginManager) {
37 JSDOC.PluginManager.run("onDocTagSynonym", this);
38 }
39
40 src = this.nibbleType(src);
41
42 // only some tags are allowed to have names.
43 if (this.title == "param" || this.title == "property" || this.title == "config") { // @config is deprecated
44 src = this.nibbleName(src);
45 }
46 }
47 catch(e) {
48 if (LOG) LOG.warn(e);
49 else throw e;
50 }
51 this.desc = src; // whatever is left
52
53 // example tags need to have whitespace preserved
54 if (this.title != "example") this.desc = this.desc.trim();
55
56 if (JSDOC.PluginManager) {
57 JSDOC.PluginManager.run("onDocTag", this);
58 }
59}
60
61/**
62 Automatically called when this is stringified.
63 */
64JSDOC.DocTag.prototype.toString = function() {
65 return this.desc;
66}
67
68/*t:
69 plan(1, "testing JSDOC.DocTag#toString");
70
71 var tag = new JSDOC.DocTag("param {object} date A valid date.");
72 is(""+tag, "A valid date.", "stringifying a tag returns the desc.");
73 */
74
75/**
76 Find and shift off the title of a tag.
77 @param {string} src
78 @return src
79 */
80JSDOC.DocTag.prototype.nibbleTitle = function(src) {
81 if (typeof src != "string") throw "src must be a string not "+(typeof src);
82
83 var parts = src.match(/^\s*(\S+)(?:\s([\s\S]*))?$/);
84
85 if (parts && parts[1]) this.title = parts[1];
86 if (parts && parts[2]) src = parts[2];
87 else src = "";
88
89 return src;
90}
91
92/*t:
93 plan(8, "testing JSDOC.DocTag#nibbleTitle");
94
95 var tag = new JSDOC.DocTag();
96
97 tag.init().nibbleTitle("aTitleGoesHere");
98 is(tag.title, "aTitleGoesHere", "a title can be found in a single-word string.");
99
100 var src = tag.init().nibbleTitle("aTitleGoesHere and the rest");
101 is(tag.title, "aTitleGoesHere", "a title can be found in a multi-word string.");
102 is(src, "and the rest", "the rest is returned when the title is nibbled off.");
103
104 src = tag.init().nibbleTitle("");
105 is(tag.title, "", "given an empty string the title is empty.");
106 is(src, "", "the rest is empty when the tag is empty.");
107
108 var src = tag.init().nibbleTitle(" aTitleGoesHere\n a description");
109 is(tag.title, "aTitleGoesHere", "leading and trailing spaces are not part of the title.");
110 is(src, " a description", "leading spaces (less one) are part of the description.");
111
112 tag.init().nibbleTitle("a.Title::Goes_Here foo");
113 is(tag.title, "a.Title::Goes_Here", "titles with punctuation are allowed.");
114 */
115
116/**
117 Find and shift off the type of a tag.
118 @requires frame/String.js
119 @param {string} src
120 @return src
121 */
122JSDOC.DocTag.prototype.nibbleType = function(src) {
123 if (typeof src != "string") throw "src must be a string not "+(typeof src);
124
125 if (src.match(/^\s*\{/)) {
126 var typeRange = src.balance("{", "}");
127 if (typeRange[1] == -1) {
128 throw "Malformed comment tag ignored. Tag type requires an opening { and a closing }: "+src;
129 }
130 this.type = src.substring(typeRange[0]+1, typeRange[1]).trim();
131 this.type = this.type.replace(/\s*,\s*/g, "|"); // multiples can be separated by , or |
132 src = src.substring(typeRange[1]+1);
133 }
134
135 return src;
136}
137
138/*t:
139 plan(5, "testing JSDOC.DocTag.parser.nibbleType");
140 requires("../frame/String.js");
141
142 var tag = new JSDOC.DocTag();
143
144 tag.init().nibbleType("{String[]} aliases");
145 is(tag.type, "String[]", "type can have non-alpha characters.");
146
147 tag.init().nibbleType("{ aTypeGoesHere } etc etc");
148 is(tag.type, "aTypeGoesHere", "type is trimmed.");
149
150 tag.init().nibbleType("{ oneType, twoType ,\n threeType } etc etc");
151 is(tag.type, "oneType|twoType|threeType", "multiple types can be separated by commas.");
152
153 var error;
154 try { tag.init().nibbleType("{widget foo"); }
155 catch(e) { error = e; }
156 is(typeof error, "string", "malformed tag type throws error.");
157 isnt(error.indexOf("Malformed"), -1, "error message tells tag is malformed.");
158 */
159
160/**
161 Find and shift off the name of a tag.
162 @requires frame/String.js
163 @param {string} src
164 @return src
165 */
166JSDOC.DocTag.prototype.nibbleName = function(src) {
167 if (typeof src != "string") throw "src must be a string not "+(typeof src);
168
169 src = src.trim();
170
171 // is optional?
172 if (src.charAt(0) == "[") {
173 var nameRange = src.balance("[", "]");
174 if (nameRange[1] == -1) {
175 throw "Malformed comment tag ignored. Tag optional name requires an opening [ and a closing ]: "+src;
176 }
177 this.name = src.substring(nameRange[0]+1, nameRange[1]).trim();
178 this.isOptional = true;
179
180 src = src.substring(nameRange[1]+1);
181
182 // has default value?
183 var nameAndValue = this.name.split("=");
184 if (nameAndValue.length) {
185 this.name = nameAndValue.shift().trim();
186 this.defaultValue = nameAndValue.join("=");
187 }
188 }
189 else {
190 var parts = src.match(/^(\S+)(?:\s([\s\S]*))?$/);
191 if (parts) {
192 if (parts[1]) this.name = parts[1];
193 if (parts[2]) src = parts[2].trim();
194 else src = "";
195 }
196 }
197
198 return src;
199}
200
201/*t:
202 requires("../frame/String.js");
203 plan(9, "testing JSDOC.DocTag.parser.nibbleName");
204
205 var tag = new JSDOC.DocTag();
206
207 tag.init().nibbleName("[foo] This is a description.");
208 is(tag.isOptional, true, "isOptional syntax is detected.");
209 is(tag.name, "foo", "optional param name is found.");
210
211 tag.init().nibbleName("[foo] This is a description.");
212 is(tag.isOptional, true, "isOptional syntax is detected when no type.");
213 is(tag.name, "foo", "optional param name is found when no type.");
214
215 tag.init().nibbleName("[foo=7] This is a description.");
216 is(tag.name, "foo", "optional param name is found when default value.");
217 is(tag.defaultValue, 7, "optional param default value is found when default value.");
218
219 //tag.init().nibbleName("[foo= a value] This is a description.");
220 //is(tag.defaultValue, " a value", "optional param default value is found when default value has spaces (issue #112).");
221
222 tag.init().nibbleName("[foo=[]] This is a description.");
223 is(tag.defaultValue, "[]", "optional param default value is found when default value is [] (issue #95).");
224
225 tag.init().nibbleName("[foo=a=b] This is a description.");
226 is(tag.name, "foo", "optional param name is found when default value is a=b.");
227 is(tag.defaultValue, "a=b", "optional param default value is found when default value is a=b.")
228 */
229
230/*t:
231 plan(32, "Testing JSDOC.DocTag.parser.");
232 requires("../frame/String.js");
233
234 var tag = new JSDOC.DocTag();
235
236 is(typeof tag, "object", "JSDOC.DocTag.parser with an empty string returns an object.");
237 is(typeof tag.title, "string", "returned object has a string property 'title'.");
238 is(typeof tag.type, "string", "returned object has a string property 'type'.");
239 is(typeof tag.name, "string", "returned object has a string property 'name'.");
240 is(typeof tag.defaultValue, "string", "returned object has a string property 'defaultValue'.");
241 is(typeof tag.isOptional, "boolean", "returned object has a boolean property 'isOptional'.");
242 is(typeof tag.desc, "string", "returned object has a string property 'desc'.");
243
244 tag = new JSDOC.DocTag("param {widget} foo");
245 is(tag.title, "param", "param title is found.");
246 is(tag.name, "foo", "param name is found when desc is missing.");
247 is(tag.desc, "", "param desc is empty when missing.");
248
249 tag = new JSDOC.DocTag("param {object} date A valid date.");
250 is(tag.name, "date", "param name is found with a type.");
251 is(tag.type, "object", "param type is found.");
252 is(tag.desc, "A valid date.", "param desc is found with a type.");
253
254 tag = new JSDOC.DocTag("param aName a description goes\n here.");
255 is(tag.name, "aName", "param name is found without a type.");
256 is(tag.desc, "a description goes\n here.", "param desc is found without a type.");
257
258 tag = new JSDOC.DocTag("param {widget}");
259 is(tag.name, "", "param name is empty when it is not given.");
260
261 tag = new JSDOC.DocTag("param {widget} [foo] This is a description.");
262 is(tag.name, "foo", "optional param name is found.");
263
264 tag = new JSDOC.DocTag("return {aType} This is a description.");
265 is(tag.type, "aType", "when return tag has no name, type is found.");
266 is(tag.desc, "This is a description.", "when return tag has no name, desc is found.");
267
268 tag = new JSDOC.DocTag("author Joe Coder <jcoder@example.com>");
269 is(tag.title, "author", "author tag has a title.");
270 is(tag.type, "", "the author tag has no type.");
271 is(tag.name, "", "the author tag has no name.");
272 is(tag.desc, "Joe Coder <jcoder@example.com>", "author tag has desc.");
273
274 tag = new JSDOC.DocTag("private \t\n ");
275 is(tag.title, "private", "private tag has a title.");
276 is(tag.type, "", "the private tag has no type.");
277 is(tag.name, "", "the private tag has no name.");
278 is(tag.desc, "", "private tag has no desc.");
279
280 tag = new JSDOC.DocTag("example\n example(code);\n more();");
281 is(tag.desc, " example(code);\n more();", "leading whitespace (less one) in examples code is preserved.");
282
283 tag = new JSDOC.DocTag("param theName \n");
284 is(tag.name, "theName", "name only is found.");
285
286 tag = new JSDOC.DocTag("type theDesc \n");
287 is(tag.desc, "theDesc", "desc only is found.");
288
289 tag = new JSDOC.DocTag("type {theType} \n");
290 is(tag.type, "theType", "type only is found.");
291
292 tag = new JSDOC.DocTag("");
293 is(tag.title, "", "title is empty when tag is empty.");
294 */