PageRenderTime 31ms CodeModel.GetById 16ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

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

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