Commit | Line | Data |
---|---|---|
629a09ae DV |
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 | } |