sbin/res/jsdoc/app/lib/JSDOC/SymbolSet.js
changeset 1072 ac1eacb3aa33
parent 1071 02c04d2c8fd8
child 1073 687133dc13cf
equal deleted inserted replaced
1071:02c04d2c8fd8 1072:ac1eacb3aa33
     1 /** @constructor */
       
     2 JSDOC.SymbolSet = function() {
       
     3 	this.init();
       
     4 }
       
     5 
       
     6 JSDOC.SymbolSet.prototype.init = function() {
       
     7 	this._index = new Hash();
       
     8 }
       
     9 
       
    10 JSDOC.SymbolSet.prototype.keys = function() {
       
    11 	return this._index.keys();
       
    12 }
       
    13 
       
    14 JSDOC.SymbolSet.prototype.hasSymbol = function(alias) {
       
    15 	return this._index.hasKey(alias);
       
    16 }
       
    17 
       
    18 JSDOC.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 
       
    26 JSDOC.SymbolSet.prototype.getSymbol = function(alias) {
       
    27 	if (this.hasSymbol(alias)) return this._index.get(alias);
       
    28 }
       
    29 
       
    30 JSDOC.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 
       
    37 JSDOC.SymbolSet.prototype.toArray = function() {
       
    38 	return this._index.values();
       
    39 }
       
    40 
       
    41 JSDOC.SymbolSet.prototype.deleteSymbol = function(alias) {
       
    42 	if (!this.hasSymbol(alias)) return;
       
    43 	this._index.drop(alias);
       
    44 }
       
    45 
       
    46 JSDOC.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 
       
    53 JSDOC.SymbolSet.prototype.relate = function() {
       
    54 	this.resolveBorrows();
       
    55 	this.resolveMemberOf();
       
    56 	this.resolveAugments();
       
    57 }
       
    58 
       
    59 JSDOC.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 		
       
    67 if (/#$/.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 
       
   112 JSDOC.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 
       
   199 JSDOC.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 
       
   208 JSDOC.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 }