fix overwrite symbols - not sure why it was enabled?
[roojspacker] / roojspacker / SymbolSet.vala
1  
2 namespace JSDOC {
3
4         public class SymbolSet  : Object {
5
6                 private Gee.HashMap<string,Symbol> __index = null;
7                 
8                 
9                 public Json.Object toJson()
10                 {
11                         var ret = new Json.Object();
12                          foreach(var k in this._index.keys) {
13                 ret.set_object_member(k, this._index.get(k).toJson());
14                 }
15                 return ret;
16                 }
17                 
18                 
19                 public Gee.HashMap<string,Symbol> _index {
20                         get {
21                                 if (this.__index == null) {
22                                         GLib.debug("Creating new Symbolset array");
23                                         this.__index = new Gee.HashMap<string,Symbol>();
24                                 }
25                                 return this.__index;
26                         }
27                 }
28                 // CTOR - do nothing..?
29                 public SymbolSet ()
30                 {
31
32                 }
33                  
34
35         public Gee.ArrayList<string> keys() 
36         {
37             var  r= new Gee.ArrayList<string>();
38             foreach(var k in this._index.keys) {
39                 r.add(k);
40                 }
41                 return r;
42
43         }
44          public Gee.ArrayList<Symbol> values() 
45         {
46             var  r= new Gee.ArrayList<Symbol>();
47             foreach(var k in this._index.values) {
48                 r.add(k);
49                 }
50                 return r;
51
52         }
53
54         public bool hasSymbol(string alias) 
55         {
56             return this._index.has_key(alias);
57             //return this.keys().indexOf(alias) > -1;
58         }
59
60         public void addSymbol (Symbol symbol) {
61              GLib.debug("ADDING SYMBOL: %s",symbol.alias);
62             
63              
64             if (this.hasSymbol(symbol.alias)) {
65                 GLib.warning("Skip Overwriting symbol documentation for: %s.",symbol.alias);
66                 return;
67             }
68             this._index.set(symbol.alias,  symbol);
69         }
70
71         public Symbol? getSymbol (string alias) {
72             
73             if (this.hasSymbol(alias)) return this._index.get(alias);
74             return null;
75         }
76 /*/
77         toArray : function() {
78             var found = [];
79             for (var p in this._index) {
80                 found.push(this._index[p]);
81             }
82             return found;
83         },
84         */
85         /**
86          * for serializing
87          *
88         toJSON : function() {
89             return {
90                 '*object' : 'SymbolSet',
91                 _index : this._index
92             };
93             
94         },
95 */
96
97         public void deleteSymbol  (string alias) {
98             if (!this.hasSymbol(alias)) return;
99             this._index.unset(alias);
100         } 
101
102         public string renameSymbol (string oldName, string newName) {
103             // todo: should check if oldname or newname already exist
104             if (!this.hasSymbol(oldName)) {
105                 GLib.error("Cant rename " + oldName + " to " + newName + " As it doesnt exist");
106             } 
107             this._index.set(newName, this._index.get(oldName));
108             this.deleteSymbol(oldName);
109             this._index.get(newName).alias = newName;
110             return newName;
111         }
112
113         public void relate() 
114         {
115             GLib.debug("RELATE called");
116             foreach(var s in this._index.keys) {
117                 GLib.debug("%s", this._index.get(s).asString());
118                 }
119             this.resolveBorrows();
120             this.resolveMemberOf();
121             this.resolveAugments();
122                          GLib.debug("AFTER RELATE called");
123                 foreach(var s in this._index.keys) {
124                 GLib.debug("%s", this._index.get(s).asString());
125                 }
126         }
127
128         void resolveBorrows() 
129         {
130
131             return; // this code is not needed- we do not use @inherits
132             /*
133             foreach (var p in this._index.keys) {
134                 var symbol = this._index.get(p);
135                 
136                 
137                 
138                 if (symbol.is("FILE") || symbol.is("GLOBAL")) continue;
139                 
140                 var borrows = symbol.inherits;
141                 for (var i = 0; i < borrows.size; i++) {
142                     var borrowed = this.getSymbol(borrows.get(i).alias);
143                     if (!borrowed) {
144                         imports.BuildDocs.Options.LOG.warn("Can't borrow undocumented "+borrows[i].alias+".");
145                         continue;
146                     }
147                     
148                     var borrowAsName = borrows[i].as;
149                     var borrowAsAlias = borrowAsName;
150                     if (!borrowAsName) {
151                         imports.BuildDocs.Options.LOG.warn("Malformed @borrow, 'as' is required.");
152                         continue;
153                     }
154                     
155                     if (borrowAsName.length > symbol.alias.length && borrowAsName.indexOf(symbol.alias) == 0) {
156                         borrowAsName = borrowAsName.replace(borrowed.alias, "");
157                     }
158                     else {
159                         var joiner = "";
160                         if (borrowAsName.charAt(0) != "#") joiner = ".";
161                         borrowAsAlias = borrowed.alias + joiner + borrowAsName;
162                     }
163                     
164                     borrowAsName = borrowAsName.replace(/^[#.]/, "");
165                             
166                     if (this.hasSymbol(borrowAsAlias)) continue;
167
168                     var clone = borrowed.clone();
169                     clone.name = borrowAsName;
170                     clone.alias = borrowAsAlias;
171                     this.addSymbol(clone);
172                 }
173             }
174                         */
175         }
176
177         void resolveMemberOf () 
178         {
179             if (this._index.keys.size < 1) {
180                     return;
181             }
182             foreach (var p in this.keys()) {
183                 var symbol = this.getSymbol(p);
184                 
185                 if (symbol.is("FILE") || symbol.is("GLOBAL")) {
186                         continue;
187                 }
188                 
189                 // the memberOf value was provided in the @memberOf tag
190                 
191                 GLib.debug("Resolve: %s memberOf=%s", symbol.alias, symbol.memberOf);
192                                 if (symbol.memberOf.length > 0) {
193                         var regex = new GLib.Regex("^("+symbol.memberOf+"[.#-])(.+)$");
194                         GLib.MatchInfo minfo;
195                     var parts = regex.match_full(symbol.alias, -1, 0, 0 , out minfo);
196                     
197                     // like foo.bar is a memberOf foo
198                     if (parts) {                         
199                         symbol.memberOf = minfo.fetch(1);
200                         symbol.private_name = minfo.fetch(2);
201                     }
202                     // like bar is a memberOf foo
203                     else {
204                         var joiner = symbol.memberOf.substring(symbol.memberOf.length-1);
205                         if (!/[.#-]/.match(joiner)) symbol.memberOf += ".";
206                         
207                         this.renameSymbol(p, symbol.memberOf + symbol.name);
208                     }
209                 } else {
210                 // the memberOf must be calculated
211                 
212                         GLib.MatchInfo minfo;                
213                     var parts = /^(.*[.#-])([^.#-]+)$/.match_full(symbol.alias, -1, 0, 0 , out minfo);
214
215                     if (parts) {
216                         symbol.memberOf = minfo.fetch(1);
217                         symbol.private_name = minfo.fetch(2);
218                     }
219                 }
220
221                 // set isStatic, isInner
222                 if (symbol.memberOf.length > 0 && !symbol.is("CONSTRUCTOR")) {
223                     switch (symbol.memberOf[symbol.memberOf.length-1]) {
224                         case '#' :
225                             symbol.isStatic = false;
226                             symbol.isInner = false;
227                             break;
228                             
229                         case '.' :
230                             symbol.isStatic = true;
231                             symbol.isInner = false;
232                             break;
233                             
234                         case '-' :
235                             symbol.isStatic = false;
236                             symbol.isInner = true;
237                             break;
238                             
239                     }
240                 }
241                  
242                 // unowned methods and fields belong to the global object
243                 if (!symbol.is("CONSTRUCTOR") && !symbol.isNamespace && symbol.memberOf == "") {
244                     symbol.memberOf = "_global_";
245                 }
246                 
247                 // clean up
248                 if (/[.#-]$/.match(symbol.memberOf)) {
249                     symbol.memberOf = symbol.memberOf.substring(0, symbol.memberOf.length-1);
250                 }
251                 //print("looking for memberOf: " + symbol.memberOf + " FOR " + symbol.alias);
252                 // add to parent's methods or properties list
253                 GLib.debug("Trying to add '%s' to '%s'", symbol.alias, symbol.memberOf);
254                 
255                 if (symbol.memberOf.length > 0) {
256                     var container = this.getSymbol(symbol.memberOf);
257                     if (container == null) {
258                             GLib.debug("Could not find container for '%s'", symbol.memberOf);
259                         if (SymbolSet.isBuiltin(symbol.memberOf)) {
260                             container = DocParser.addBuiltin(symbol.memberOf);
261                         }
262                         else {
263                            // print("symbol NOT a BUILT IN - createing a container");
264                             // Eg. Ext.y.z (missing y)
265                             // we need to add in the missing symbol...
266                             container = new Symbol.new_populate_with_args(
267                                 symbol.memberOf, new Gee.ArrayList<string>(), 
268                                                 "OBJECT", new DocComment(""));
269                             container.isNamespace = true;
270                             this.addSymbol( container );
271                            // print(container.toSource());
272                             //container = this.getSymbol(symbol.memberOf);
273                             // fake container ... so dont ad symbols to it..
274                             continue;
275                             container = null;
276                             //LOG.warn("Can't document "+symbol.name +" as a member of undocumented symbol "+symbol.memberOf+".");
277                             //LOG.warn("We only have the following symbols: \n" + 
278                             //    this.keys.toSource());
279                         }
280                     }
281                     
282                     if (container != null && (!container.isNamespace || container.isStatic)) {
283                             GLib.debug("Calling addMember  for '%s' onto '%s'", symbol.alias, container.alias);                    
284                          container.addMember(symbol);
285                          }
286                 }
287             }
288
289         }
290
291         void resolveAugments () 
292         {
293             // does this sort out multiple extends???
294             
295             foreach (var p in this._index.keys) {
296                 var symbol = this.getSymbol(p);
297                 this.buildAugmentsList(symbol); /// build heirachy of inheritance...
298                 if (symbol.alias == "_global_" || symbol.is("FILE")) continue;
299                 
300                 var augments = symbol.augments;
301                 for(var ii = 0, il = augments.size; ii < il; ii++) {
302                     var contributer = this.getSymbol(augments[ii]);
303                     
304                      
305                     if (contributer != null) {
306                         //contributer.childClasses.add(symbol.alias); << removed we do this in one go later.
307                         symbol.inheritsFrom.add(contributer.alias);
308                         //if (!isUnique(symbol.inheritsFrom)) {
309                         //    imports.BuildDocs.Options.LOG.warn("Can't resolve augments: Circular reference: "+symbol.alias+" inherits from "+contributer.alias+" more than once.");
310                         //}
311                         //else {
312                             var cmethods = contributer.methods;
313                             var cproperties = contributer.properties;
314                             var cfgs = contributer.cfgs;
315                             for (var ci = 0, cl = cmethods.size; ci < cl; ci++) {   
316                                 symbol.inherit(cmethods[ci]);
317                             } 
318                             for (var ci = 0, cl = cproperties.size; ci < cl; ci++) {
319                                 symbol.inherit(cproperties[ci]);
320                             }
321                             foreach (var ci in cfgs.keys) {
322                                 symbol.addConfig(cfgs[ci]);
323                             }
324                             
325                                 
326                         //}
327                     }
328                     else {
329                         GLib.warning("Can't augment contributer: '%s', not found. FOR: %s",
330                                 augments[ii], symbol.alias
331                         );
332                         //LOG.warn("We only have the following symbols: \n" + 
333                           //      this.keys().toSource().split(",").join(",    \n"));
334                        }
335         
336                 }
337             }
338             
339         }
340
341
342                  void addAugments (Symbol symbol, Gee.ArrayList<string> alist, bool forceit) 
343                  { // returns number added..
344                 if (alist.size < 1) {
345                     return;
346                 }
347                 //print("buildAugmentsList:addAugments" + alist.length);
348                 //var rval = 0;
349                 for(var ii = 0; ii < alist.size; ii++) {
350                     //print("getAlias:" + alist[ii]);
351                     if (alist[ii] == symbol.alias) {
352                         continue;
353                     }
354                     var contributer = this.getSymbol(alist[ii]);
355                     if (contributer == null) {
356                         continue;
357                     }
358                     
359                     if (!forceit && symbol.augments.contains(alist[ii])) {
360                         continue;
361                     }
362                     if (symbol.augments.index_of(alist[ii]) < 0) {
363                         symbol.augments.add(alist[ii]);
364                     }
365                         
366                     
367                     this.addAugments(symbol, contributer.augments,false);
368                     
369                     //rval++;
370                 }
371                // print("buildAugmentsList: ADDED:" + rval);
372                // return rval;
373             }
374
375         void buildAugmentsList (Symbol symbol)
376         {
377                 
378                 this.addAugments(symbol, symbol.augments, true);
379                 
380             
381             
382         }
383         public static bool isBuiltin(string name)
384                 {
385                         for (var i =0 ; i < SymbolSet.coreObjects.length; i++ ){ 
386                                 if (name ==  SymbolSet.coreObjects[i]) {
387                                         return true;
388                                 }
389                         }
390                         return false;
391                 }
392                 static string[] coreObjects  = {
393                         "_global_", "Array" , "Boolean", "Date", "Function", 
394                             "Math", "Number", "Object", "RegExp", "String"
395                 };
396          
397         }
398         
399 }
400
401