PageRenderTime 46ms CodeModel.GetById 23ms app.highlight 19ms RepoModel.GetById 1ms app.codeStats 0ms

/tags/jsdoc_toolkit-2.4.0/jsdoc-toolkit/app/lib/JSDOC/SymbolSet.js

http://jsdoc-toolkit.googlecode.com/
JavaScript | 243 lines | 190 code | 38 blank | 15 comment | 62 complexity | a669dde27455515160675d81e0a06dbd MD5 | raw file
  1/** @constructor */
  2JSDOC.SymbolSet = function() {
  3	this.init();
  4}
  5
  6JSDOC.SymbolSet.prototype.init = function() {
  7	this._index = new Hash();
  8}
  9
 10JSDOC.SymbolSet.prototype.keys = function() {
 11	return this._index.keys();
 12}
 13
 14JSDOC.SymbolSet.prototype.hasSymbol = function(alias) {
 15	return this._index.hasKey(alias);
 16}
 17
 18JSDOC.SymbolSet.prototype.addSymbol = function(symbol) {
 19	if (JSDOC.opt.a && this.hasSymbol(symbol.alias)) {
 20		LOG.warn("Overwriting symbol documentation for: " + symbol.alias + ".");
 21		this.deleteSymbol(symbol.alias);
 22	}
 23	this._index.set(symbol.alias, symbol);
 24}
 25
 26JSDOC.SymbolSet.prototype.getSymbol = function(alias) {
 27	if (this.hasSymbol(alias)) return this._index.get(alias);
 28}
 29
 30JSDOC.SymbolSet.prototype.getSymbolByName = function(name) {
 31	for (var p = this._index.first(); p; p = this._index.next()) {
 32		var symbol = p.value;
 33		if (symbol.name == name) return symbol;
 34	}
 35}
 36
 37JSDOC.SymbolSet.prototype.toArray = function() {
 38	return this._index.values();
 39}
 40
 41JSDOC.SymbolSet.prototype.deleteSymbol = function(alias) {
 42	if (!this.hasSymbol(alias)) return;
 43	this._index.drop(alias);
 44}
 45
 46JSDOC.SymbolSet.prototype.renameSymbol = function(oldName, newName) {
 47	// todo: should check if oldname or newname already exist
 48	this._index.replace(oldName, newName);
 49	this._index.get(newName).alias = newName;
 50	return newName;
 51}
 52
 53JSDOC.SymbolSet.prototype.relate = function() {
 54	this.resolveBorrows();
 55	this.resolveMemberOf();
 56	this.resolveAugments();
 57}
 58
 59JSDOC.SymbolSet.prototype.resolveBorrows = function() {
 60	for (var p = this._index.first(); p; p = this._index.next()) {
 61		var symbol = p.value;
 62		if (symbol.is("FILE") || symbol.is("GLOBAL")) continue;
 63		
 64		var borrows = symbol.inherits;
 65		for (var i = 0; i < borrows.length; i++) {
 66		
 67if (/#$/.test(borrows[i].alias)) {
 68	LOG.warn("Attempted to borrow entire instance of "+borrows[i].alias+" but that feature is not yet implemented.");
 69	return;
 70}
 71			var borrowed = this.getSymbol(borrows[i].alias);
 72			
 73			if (!borrowed) {
 74				LOG.warn("Can't borrow undocumented "+borrows[i].alias+".");
 75				continue;
 76			}
 77
 78			if (borrows[i].as == borrowed.alias) {
 79				var assumedName = borrowed.name.split(/([#.-])/).pop();
 80				borrows[i].as = symbol.name+RegExp.$1+assumedName;
 81				LOG.inform("Assuming borrowed as name is "+borrows[i].as+" but that feature is experimental.");
 82			}
 83			
 84			var borrowAsName = borrows[i].as;
 85			var borrowAsAlias = borrowAsName;
 86			if (!borrowAsName) {
 87				LOG.warn("Malformed @borrow, 'as' is required.");
 88				continue;
 89			}
 90			
 91			if (borrowAsName.length > symbol.alias.length && borrowAsName.indexOf(symbol.alias) == 0) {
 92				borrowAsName = borrowAsName.replace(borrowed.alias, "")
 93			}
 94			else {
 95				var joiner = "";
 96				if (borrowAsName.charAt(0) != "#") joiner = ".";
 97				borrowAsAlias = borrowed.alias + joiner + borrowAsName;
 98			}
 99			
100			borrowAsName = borrowAsName.replace(/^[#.]/, "");
101					
102			if (this.hasSymbol(borrowAsAlias)) continue;
103
104			var clone = borrowed.clone();
105			clone.name = borrowAsName;
106			clone.alias = borrowAsAlias;
107			this.addSymbol(clone);
108		}
109	}
110}
111
112JSDOC.SymbolSet.prototype.resolveMemberOf = function() {
113	for (var p = this._index.first(); p; p = this._index.next()) {
114		var symbol = p.value;
115
116		if (symbol.is("FILE") || symbol.is("GLOBAL")) continue;
117		
118		// the memberOf value was provided in the @memberOf tag
119		else if (symbol.memberOf) {			
120			// like foo.bar is a memberOf foo
121			if (symbol.alias.indexOf(symbol.memberOf) == 0) {
122				var memberMatch = new RegExp("^("+symbol.memberOf+")[.#-]?(.+)$");
123				var aliasParts = symbol.alias.match(memberMatch);
124				
125				if (aliasParts) {
126					symbol.memberOf = aliasParts[1];
127					symbol.name = aliasParts[2];
128				}
129				
130				var nameParts = symbol.name.match(memberMatch);
131
132				if (nameParts) {
133					symbol.name = nameParts[2];
134				}
135			}
136			// like bar is a memberOf foo
137			else {
138				var joiner = symbol.memberOf.charAt(symbol.memberOf.length-1);
139				if (!/[.#-]/.test(joiner)) symbol.memberOf += ".";
140				this.renameSymbol(symbol.alias, symbol.memberOf + symbol.name);
141			}
142		}
143		// the memberOf must be calculated
144		else {
145			var parts = symbol.alias.match(/^(.*[.#-])([^.#-]+)$/);
146
147			if (parts) {
148				symbol.memberOf = parts[1];
149				symbol.name = parts[2];				
150			}
151		}
152
153		// set isStatic, isInner
154		if (symbol.memberOf) {
155			switch (symbol.memberOf.charAt(symbol.memberOf.length-1)) {
156				case '#' :
157					symbol.isStatic = false;
158					symbol.isInner = false;
159				break;
160				case '.' :
161					symbol.isStatic = true;
162					symbol.isInner = false;
163				break;
164				case '-' :
165					symbol.isStatic = false;
166					symbol.isInner = true;
167				break;
168				default: // memberOf ends in none of the above
169					symbol.isStatic = true;
170				break;
171			}
172		}
173		
174		// unowned methods and fields belong to the global object
175		if (!symbol.is("CONSTRUCTOR") && !symbol.isNamespace && symbol.memberOf == "") {
176			symbol.memberOf = "_global_";
177		}
178
179		// clean up
180		if (symbol.memberOf.match(/[.#-]$/)) {
181			symbol.memberOf = symbol.memberOf.substr(0, symbol.memberOf.length-1);
182		}
183		// add to parent's methods or properties list
184		if (symbol.memberOf) {
185
186			var container = this.getSymbol(symbol.memberOf);
187			if (!container) {
188				if (JSDOC.Lang.isBuiltin(symbol.memberOf)) container = JSDOC.Parser.addBuiltin(symbol.memberOf);
189				else {
190					LOG.warn("Trying to document "+symbol.name +" as a member of undocumented symbol "+symbol.memberOf+".");
191				}
192			}
193			
194			if (container) container.addMember(symbol);
195		}
196	}
197}
198
199JSDOC.SymbolSet.prototype.resolveAugments = function() {
200	for (var p = this._index.first(); p; p = this._index.next()) {
201		var symbol = p.value;
202		
203		if (symbol.alias == "_global_" || symbol.is("FILE")) continue;
204		JSDOC.SymbolSet.prototype.walk.apply(this, [symbol]);
205	}
206}
207
208JSDOC.SymbolSet.prototype.walk = function(symbol) {
209	var augments = symbol.augments;
210	for(var i = 0; i < augments.length; i++) {
211		var contributer = this.getSymbol(augments[i]);
212		if (!contributer && JSDOC.Lang.isBuiltin(''+augments[i])) {
213			contributer = new JSDOC.Symbol("_global_."+augments[i], [], augments[i], new JSDOC.DocComment("Built in."));
214			contributer.isNamespace = true;
215			contributer.srcFile = "";
216			contributer.isPrivate = false;
217			JSDOC.Parser.addSymbol(contributer);
218		}
219		
220		if (contributer) {			
221			if (contributer.augments.length) {
222				JSDOC.SymbolSet.prototype.walk.apply(this, [contributer]);
223			}
224			
225			symbol.inheritsFrom.push(contributer.alias);
226			//if (!isUnique(symbol.inheritsFrom)) {
227			//	LOG.warn("Can't resolve augments: Circular reference: "+symbol.alias+" inherits from "+contributer.alias+" more than once.");
228			//}
229			//else {
230				var cmethods = contributer.methods;
231				var cproperties = contributer.properties;
232				
233				for (var ci = 0, cl = cmethods.length; ci < cl; ci++) {
234					if (!cmethods[ci].isStatic) symbol.inherit(cmethods[ci]);
235				}
236				for (var ci = 0, cl = cproperties.length; ci < cl; ci++) {
237					if (!cproperties[ci].isStatic) symbol.inherit(cproperties[ci]);
238				}	
239			//}
240		}
241		else LOG.warn("Can't augment contributer: "+augments[i]+", not found.");
242	}
243}