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 } |
|