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