9cd7ed808bff7ff1ca6a31745d83adc0ee668a93
[gnome.introspection-doc-generator] / JSDOC / SymbolSet.js
1 //<script type="text/javascript">
2
3  
4 XObject         = imports.XObject.XObject;
5 // circulare references..
6 ///Options         = imports.BuildDocs.Options;
7 //Parser          = imports.Parser.Parser;
8 //Symbol          = imports.Symbol.Symbol;
9 DocComment      = imports.DocComment.DocComment;
10
11
12 SymbolSet = XObject.define(
13     function() {
14         this.init();
15     },
16     Object,
17     {
18         
19         init : function() {
20             this._index = {};
21         },
22
23         keys : function() {
24             var found = [];
25             for (var p in this._index) {
26                 found.push(p);
27             }
28             return found;
29         },
30
31
32         hasSymbol : function(alias) {
33             return this.keys().indexOf(alias) > -1;
34         },
35
36         addSymbol : function(symbol) {
37             //print("ADDING SYMBOL:"+symbol.alias.toString());
38             
39             if (this.hasSymbol(symbol.alias)) {
40                 imports.BuildDocs.Options.LOG.warn("Overwriting symbol documentation for: "+symbol.alias + ".");
41             }
42             this._index[symbol.alias] = symbol;
43         },
44
45         getSymbol : function(alias) {
46             
47             if (this.hasSymbol(alias)) return this._index[alias];
48             return false;
49         },
50
51         toArray : function() {
52             var found = [];
53             for (var p in this._index) {
54                 found.push(this._index[p]);
55             }
56             return found;
57         },
58
59         deleteSymbol : function(alias) {
60             if (!this.hasSymbol(alias)) return;
61             delete this._index[alias];
62         },
63
64         renameSymbol : function(oldName, newName) {
65             // todo: should check if oldname or newname already exist
66             if (typeof(this._index[oldName]) == "undefined") {
67                 throw "Cant rename " + oldName + " to " + newName + " As it doesnt exist";
68                }
69             this._index[newName] = this._index[oldName];
70             this.deleteSymbol(oldName);
71             this._index[newName].alias = newName;
72             return newName;
73         },
74
75         relate : function() {
76             this.resolveBorrows();
77             this.resolveMemberOf();
78             this.resolveAugments();
79         },
80
81         resolveBorrows : function() {
82             for (p in this._index) {
83                 var symbol = this._index[p];
84                 if (symbol.is("FILE") || symbol.is("GLOBAL")) continue;
85                 
86                 var borrows = symbol.inherits;
87                 for (var i = 0; i < borrows.length; i++) {
88                     var borrowed = this.getSymbol(borrows[i].alias);
89                     if (!borrowed) {
90                         imports.BuildDocs.Options.LOG.warn("Can't borrow undocumented "+borrows[i].alias+".");
91                         continue;
92                     }
93                     
94                     var borrowAsName = borrows[i].as;
95                     var borrowAsAlias = borrowAsName;
96                     if (!borrowAsName) {
97                         imports.BuildDocs.Options.LOG.warn("Malformed @borrow, 'as' is required.");
98                         continue;
99                     }
100                     
101                     if (borrowAsName.length > symbol.alias.length && borrowAsName.indexOf(symbol.alias) == 0) {
102                         borrowAsName = borrowAsName.replace(borrowed.alias, "")
103                     }
104                     else {
105                         var joiner = "";
106                         if (borrowAsName.charAt(0) != "#") joiner = ".";
107                         borrowAsAlias = borrowed.alias + joiner + borrowAsName;
108                     }
109                     
110                     borrowAsName = borrowAsName.replace(/^[#.]/, "");
111                             
112                     if (this.hasSymbol(borrowAsAlias)) continue;
113
114                     var clone = borrowed.clone();
115                     clone.name = borrowAsName;
116                     clone.alias = borrowAsAlias;
117                     this.addSymbol(clone);
118                 }
119             }
120         },
121
122         resolveMemberOf : function() {
123             for (var p in this._index) {
124                 var symbol = this.getSymbol(p);
125                 
126                 if (symbol.is("FILE") || symbol.is("GLOBAL")) continue;
127                 
128                 // the memberOf value was provided in the @memberOf tag
129                 else if (symbol.memberOf) {
130                     var parts = symbol.alias.match(new RegExp("^("+symbol.memberOf+"[.#-])(.+)$"));
131                     
132                     // like foo.bar is a memberOf foo
133                     if (parts) {
134                         symbol.memberOf = parts[1];
135                         symbol.name = parts[2];
136                     }
137                     // like bar is a memberOf foo
138                     else {
139                         var joiner = symbol.memberOf.charAt(symbol.memberOf.length-1);
140                         if (!/[.#-]/.test(joiner)) symbol.memberOf += ".";
141                         
142                         this.renameSymbol(p, symbol.memberOf + symbol.name);
143                     }
144                 }
145                 // the memberOf must be calculated
146                 else {
147                     var parts = symbol.alias.match(/^(.*[.#-])([^.#-]+)$/);
148                     if (parts) {
149                         symbol.memberOf = parts[1];
150                         symbol.name = parts[2];                         
151                     }
152                 }
153
154                 // set isStatic, isInner
155                 if (symbol.memberOf) {
156                     switch (symbol.memberOf.charAt(symbol.memberOf.length-1)) {
157                         case '#' :
158                             symbol.isStatic = false;
159                             symbol.isInner = false;
160                             break;
161                             
162                         case '.' :
163                             symbol.isStatic = true;
164                             symbol.isInner = false;
165                             break;
166                             
167                         case '-' :
168                             symbol.isStatic = false;
169                             symbol.isInner = true;
170                             break;
171                             
172                     }
173                 }
174                 
175                 // unowned methods and fields belong to the global object
176                 if (!symbol.is("CONSTRUCTOR") && !symbol.isNamespace && symbol.memberOf == "") {
177                     symbol.memberOf = "_global_";
178                 }
179                 
180                 // clean up
181                 if (symbol.memberOf.match(/[.#-]$/)) {
182                     symbol.memberOf = symbol.memberOf.substr(0, symbol.memberOf.length-1);
183                 }
184                 //print("looking for memberOf: " + symbol.memberOf + " FOR " + symbol.alias);
185                 // add to parent's methods or properties list
186                 if (symbol.memberOf) {
187                     var container = this.getSymbol(symbol.memberOf);
188                     if (!container) {
189                         if (SymbolSet.isBuiltin(symbol.memberOf)) {
190                             container = imports.Parser.Parser.addBuiltin(symbol.memberOf);
191                         }
192                         else {
193                            // print("symbol NOT a BUILT IN - createing a container");
194                             // Eg. Ext.y.z (missing y)
195                             // we need to add in the missing symbol...
196                             container = new imports.Symbol.Symbol(symbol.memberOf, [], "OBJECT", new DocComment(""));
197                             container.isNamespace = true;
198                             this.addSymbol( container );
199                            // print(container.toSource());
200                             //container = this.getSymbol(symbol.memberOf);
201                             // fake container ... so dont ad symbols to it..
202                             continue;
203                             container = false;
204                             //LOG.warn("Can't document "+symbol.name +" as a member of undocumented symbol "+symbol.memberOf+".");
205                             //LOG.warn("We only have the following symbols: \n" + 
206                             //    this.keys.toSource());
207                         }
208                     }
209                     
210                     if (container && !container.isNamespace) container.addMember(symbol);
211                 }
212             }
213         },
214
215         resolveAugments : function() {
216             // does this sort out multiple extends???
217             for (var p in this._index) {
218                 var symbol = this.getSymbol(p);
219                 this.buildAugmentsList(symbol); /// build heirachy of inheritance...
220                 if (symbol.alias == "_global_" || symbol.is("FILE")) continue;
221                 
222                 var augments = symbol.augments;
223                 for(var ii = 0, il = augments.length; ii < il; ii++) {
224                     var contributer = this.getSymbol(augments[ii]);
225                     
226                     
227                     
228                     if (contributer) {
229                         contributer.childClasses.push(symbol.alias);
230                         symbol.inheritsFrom.push(contributer.alias);
231                         if (!isUnique(symbol.inheritsFrom)) {
232                             imports.BuildDocs.Options.LOG.warn("Can't resolve augments: Circular reference: "+symbol.alias+" inherits from "+contributer.alias+" more than once.");
233                         }
234                         else {
235                             var cmethods = contributer.methods;
236                             var cproperties = contributer.properties;
237                             var cfgs = contributer.cfgs;
238                             for (var ci = 0, cl = cmethods.length; ci < cl; ci++) {   
239                                 symbol.inherit(cmethods[ci]);
240                             }
241                             for (var ci = 0, cl = cproperties.length; ci < cl; ci++) {
242                                 symbol.inherit(cproperties[ci]);
243                             }
244                             for (var ci in cfgs) {
245                                 symbol.addConfig(cfgs[ci]);
246                             }
247                             
248                                 
249                         }
250                     }
251                     else {
252                         
253                         imports.BuildDocs.Options.LOG.warn("Can't augment contributer: '"+augments[ii]+"', not found. FOR: " + symbol.alias);
254                         
255                         //LOG.warn("We only have the following symbols: \n" + 
256                           //      this.keys().toSource().split(",").join(",    \n"));
257                        }
258
259                 }
260             }
261         },
262
263         buildAugmentsList : function(symbol)
264         {
265             // basic idea is to add all the child extends to the parent.. without looping forever..
266             
267             if (!symbol.augments.length) {
268                 return;
269             }
270             
271             var _t = this;
272             print("buildAugmentsList:" + symbol.alias);
273             var addAugments = function (alist, forceit) { // returns number added..
274                 if (!alist.length) {
275                     return 0;
276                 }
277                 print("buildAugmentsList:addAugments" + alist.length);
278                 var rval = 0;
279                 for(var ii = 0; ii < alist.length; ii++) {
280                     print("getAlias:" + alist[ii]);
281                     if (alist[ii] == symbol.alias) {
282                         continue;
283                     }
284                     var contributer = _t.getSymbol(alist[ii]);
285                     if (!contributer) {
286                         continue;
287                     }
288                     
289                     if (!forceit && symbol.augments.indexOf(alist[ii]) > -1) {
290                         continue;
291                     }
292                     if (symbol.augments.indexOf(alist[ii]) < 0) {
293                         symbol.augments.push(alist[ii]);
294                     }
295                         
296                     
297                     addAugments(contributer.augments,false);
298                     
299                     rval++;
300                 }
301                 print("buildAugmentsList: ADDED:" + rval);
302                 return rval;
303             }
304             addAugments(symbol.augments, true);
305             //while(addAugments(symbol.augments) >  0) { }
306             
307         }
308 })
309
310 SymbolSet.isBuiltin = function(name) {
311     return (SymbolSet.isBuiltin.coreObjects.indexOf(name) > -1);
312 }
313 SymbolSet.isBuiltin .coreObjects = [
314     '_global_', 'Array', 'Boolean', 'Date', 'Function', 
315     'Math', 'Number', 'Object', 'RegExp', 'String'
316 ];