PageRenderTime 14ms CodeModel.GetById 2ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/tags/jsdoc_toolkit-2.2.1/jsdoc-toolkit/app/lib/JSDOC/DocTag.js

http://jsdoc-toolkit.googlecode.com/
JavaScript | 294 lines | 89 code | 28 blank | 177 comment | 42 complexity | 0baf4099c5c3bd6bd34187b41499e623 MD5 | raw file
  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 */