src/Palete/Palete.vala
[app.Builder.js] / src / Palete / Palete.vala
1
2 using Gtk;
3 namespace Palete 
4 {
5
6
7         public errordomain Error {
8                 INVALID_TYPE,
9                 NEED_IMPLEMENTING,
10                 MISSING_FILE,
11                 INVALID_VALUE
12         }
13
14         public class Usage : Object 
15         {
16                 public Gee.ArrayList<string> left;
17                 public Gee.ArrayList<string> right;
18                 public Usage(Gee.ArrayList<string> ileft, Gee.ArrayList<string> iright)
19                 {
20                         this.left = ileft;
21                         this.right=  iright;
22                 }
23                 public bool leftHas(string s)
24                 {
25                         for(var i = 0 ; i < this.left.size; i++) {
26                                 var m = this.left.get(i);
27                                 if (s == m) {
28                                         return true;
29                                 }
30                                 if (!m.contains(":")) {
31                                         continue;
32                                 }
33                                 var ar = m.split(":");
34                                 if (ar[0] == s) {
35                                         return true;
36                                 }
37                         }
38                         return false;
39                                 
40                 }
41
42                 
43         }
44
45         
46
47     static Gee.HashMap<string,Palete>? cache = null;
48     
49     public static Palete factory(string xtype)
50     {
51         if (cache == null) {
52             cache = new Gee.HashMap<string,Palete>();
53         }
54         if (cache.get(xtype) != null) {
55             return cache.get(xtype);
56         }
57         switch(xtype) {
58             case "Gtk":
59                 cache.set(xtype, new Gtk());
60                 break;
61             case "Roo":
62                 cache.set(xtype, new Roo());
63                 break;
64             default:
65                 throw new Error.INVALID_TYPE("invalid argument to Palete factory");
66         }
67         return cache.get(xtype);
68     }
69        
70
71     public abstract class Palete : Object 
72     {
73         
74        
75         public string name;
76
77                 public Gee.ArrayList<Usage> map;
78
79                 public Gee.HashMap<string,GirObject> classes; // used in roo.. 
80         
81         public Palete()
82         {
83                                 // nothing?
84                         this.map = null;
85                         this.classes = null;
86         }
87         
88         
89         //map : false, // array of mappings   left: [] , right : []
90         
91         //items : false, // the tree of nodes.
92         
93         
94
95
96         string  guessName(JsRender.Node ar) throws Error // turns the object into full name.
97         {
98             throw new Error.NEED_IMPLEMENTING("xxx. guessName needs implimenting");
99         }
100             
101
102             
103          
104
105             
106                 public string[] getChildList(string in_rval)
107         {
108
109                         if (this.map == null) {
110                                 this.load();
111                         }
112                         // empty == *top
113                         
114                         var rval = in_rval == "" ? "*top" : in_rval; 
115                                         
116                                         // should be a bit more than this..
117                                 // -> it should look for all elements that inherit 
118                                 string[] ret = {};
119                         var rt = new Gee.ArrayList<string>();
120                         for (var i = 0; i < this.map.size; i++) {
121                                 var m = this.map.get(i);
122                                         
123                                         if (!m.leftHas(rval)) {
124                                         continue;
125                                 }
126                                 print("found LEFT, adding right\n");
127                         
128                                 for(var ii =0; ii < m.right.size; ii++) {
129                                                 var l = m.right.get(ii);
130                                                 
131                                                 if (rt.index_of(l) > -1) {
132                                                         continue;
133                                                 }
134                                         //print("ADD " + string.joinv(", ", ret) + "\n");
135                                                 ret += l;
136                                         rt.add(l);
137                                         }
138                                         
139                                         
140                                 }
141                         print ("drop list for %s is:\n%s\n", rval, string.joinv("\n", ret));
142                         //console.log("DROP LIST:");
143                         //console.dump(ret);
144                         return ret;
145                                 
146         }
147
148             
149         public string[] getDropList(string rval)
150         {
151
152                         if (this.map == null) {
153                                 this.load();
154                         }
155
156                                         
157                                         // should be a bit more than this..
158                                 // -> it should look for all elements that inherit 
159                                 string[] ret = {};
160                         var rt = new Gee.ArrayList<string>();
161                         for (var i = 0; i < this.map.size; i++) {
162                                 var m = this.map.get(i);
163                                         
164                                         if (m.right.index_of(rval) < 0) {
165                                         continue;
166                                 }
167                                 //print("found RIGHT, adding left\n");
168                         
169                                 for(var ii =0; ii < m.left.size; ii++) {
170                                                 var l = m.left.get(ii);
171                                                 
172                                                 if (rt.index_of(l) > -1) {
173                                                         continue;
174                                                 }
175                                         //print("ADD " + string.joinv(", ", ret) + "\n");
176                                                 ret += l;
177                                         rt.add(l);
178                                         }
179                                         
180                                         
181                                 }
182                          print ("drop list for %s is:\n%s\n", rval, string.joinv("\n", ret));
183                         //console.log("DROP LIST:");
184                         //console.dump(ret);
185                         return ret;
186             
187         }
188       
189         public void saveTemplate (string name, JsRender.Node data)
190         {
191
192                         var gn = data.fqn();
193             // store it in user's directory..
194             var appdir =  GLib.Environment.get_home_dir() + "/.Builder"; 
195
196                         
197             if (!GLib.FileUtils.test(appdir+ "/" + gn, GLib.FileTest.IS_DIR)) {
198                                 GLib.File.new_for_path (appdir+ "/" + gn).make_directory ();
199                                 
200             }
201             GLib.FileUtils.set_contents(appdir+ "/" + gn + "/" +  name + ".json", data.toJsonString());
202             
203         }
204         
205         /**
206          * list templates - in home directory (and app dir in future...)
207          * @param {String} name  - eg. Gtk.Window..
208          * @return {Array} list of templates available..
209          */
210           
211         public  GLib.List<string> listTemplates (JsRender.Node node)
212         {
213             
214                         var gn = node.fqn();
215                                 
216                         var ret = new GLib.List<string>();
217                         var dir= GLib.Environment.get_home_dir() + "/.Builder/" + gn;
218                         if (!GLib.FileUtils.test(dir, GLib.FileTest.IS_DIR)) {
219                                 return ret;
220                         }
221                         
222
223
224                                     
225                         var f = File.new_for_path(dir);
226                         
227                                 var file_enum = f.enumerate_children(GLib.FileAttribute.STANDARD_DISPLAY_NAME, GLib.FileQueryInfoFlags.NONE, null);
228                                  
229                                 FileInfo next_file; 
230                                 while ((next_file = file_enum.next_file(null)) != null) {
231                                         var n = next_file.get_display_name();
232                                         if (!Regex.match_simple ("\\.json$", n)) {
233                                                 continue;
234                                         }
235                                         ret.append( dir + "/" + n);
236                                 }
237                                 return ret;
238             
239                 }
240  
241         public JsRender.Node? loadTemplate(string path)
242         {
243
244                         var pa = new Json.Parser();
245                         pa.load_from_file(path);
246                         var node = pa.get_root();
247
248                         if (node.get_node_type () != Json.NodeType.OBJECT) {
249                                 return null;
250                         }
251                         var obj = node.get_object ();
252
253                         var ret = new JsRender.Node();
254
255
256                         ret.loadFromJson(obj, 1);
257                         ret.ref(); // not sure if needed -- but we had a case where ret became uninitialized?
258                 
259                         return ret;
260                 }
261
262
263
264                 public   void  loadUsageFile (string fname) {
265
266
267
268                         
269                                 print("Palete Load called\n");
270                         string raw;
271                         if (!FileUtils.test (fname, FileTest.EXISTS)) {
272                                 throw new Error.MISSING_FILE(fname + " not found");
273                         }
274         
275                         FileUtils.get_contents(fname, out raw);
276                       // print(data);
277                         var data  = raw.split("\n");
278                         var state = 0;
279                         var cfg = new Gee.ArrayList<Usage>();
280                         var left = new Gee.ArrayList<string>();
281                         var right = new Gee.ArrayList<string>();
282         
283                         for (var i = 0; i < data.length; i++) {
284                                 var d = data[i].strip();
285                                 //print("READ " + d + "\n");
286                                 if (
287                                         d.length < 1
288                                         ||
289                                          Regex.match_simple ("^\\s+$", d)
290                                         ||
291                                         Regex.match_simple ("^\\s*/", d)
292                                  ){
293                                         continue;
294                                 }
295                                 
296                                     if (Regex.match_simple ("^left:", d)) { 
297                                         state = 1;
298                                         if (left.size > 0 ){
299                                             cfg.add(new Usage( left, right));
300                                                         }
301                                         left = new Gee.ArrayList<string>();
302                                                 right = new Gee.ArrayList<string>();
303                                         continue;
304                                     }
305                                      if (Regex.match_simple ("^right:", d)) { 
306                                         state = 2;
307                                         continue;
308                                     }
309                                     if (state == 1) {
310                                                         //print("add left: " + d + "\n");
311                                         left.add(d);
312                                         continue;
313                                     }
314                                                 //print("add Right: " + d + "\n");
315                                     right.add(d);
316                                     //Seed.quit();
317                                    
318                         }
319                         if (left.size > 0 ){
320                                 cfg.add(new Usage( left, right));
321                         }
322                         this.map = cfg;
323
324            }
325
326          
327                 public   void validateVala(
328                                 WindowState state,
329                                 string code, 
330                                 string property, 
331                                 string ptype,
332                                 JsRender.JsRender file,
333                                 JsRender.Node node
334                  ) 
335                 {   
336
337                         print("validate code (%s) %s\n", file.language, code);
338                          
339                 
340                          
341                         if (file.language != "vala" ) { // not sure if we need to validate property
342                                 return;
343                         }
344                         // file.project , file.path, file.build_module, ""
345                         
346                 
347                          
348                         //var cd = new JSCore.ClassDefinitionEmpty();
349                         state.valasource.checkFileWithNodePropChange(
350                                         file,
351                                         node, 
352                                         property, 
353                                         ptype,
354                                         code
355                          );
356                          
357
358                 }
359                  
360         
361         
362         
363                 public   bool  javascriptHasErrors(
364                                         WindowState state,
365                                         string code, 
366                                         string property, 
367                                         string ptype,
368                                         JsRender.JsRender file,
369                                         JsRender.Node? node, 
370                                         out Gee.HashMap<int,string> errors
371                                  ) 
372                 {   
373
374                          print("validate code (%s) ptype=%s property=%s\n", file.language, ptype, property);
375                            errors = new Gee.HashMap<int,string>();
376                 
377                         if (file.language != "js") {
378                                 return false;
379                          }
380                          if (ptype != "listener" && property.length > 0 && property[0] == '|') {
381                                 return false;
382                          }
383                         
384                         //var cd = new JSCore.ClassDefinitionEmpty();
385                         //print("TESTING CODE %s\n", code);
386                         string errmsg;
387                         var testcode = ptype == "file" ? code : "var __aaa___ = " + code;
388                         var line = Javascript.singleton().validate(
389                                                                   testcode, out errmsg);
390
391                         if (line > -1) {
392                                 if (ptype == "file") {
393                                         var err = new Json.Object();
394                                         err.set_int_member("ERR-TOTAL", 1);
395                                         var files_obj = new Json.Object();
396                                         var lines_obj = new Json.Object();
397                                         var lines_ar = new Json.Array();
398                                         lines_ar.add_string_element(errmsg);
399                                         lines_obj.set_array_member(line.to_string(), lines_ar);
400                                         files_obj.set_object_member(file.path, lines_obj);
401                                          
402                                         err.set_object_member("ERR", files_obj);
403  
404                                         state.showCompileResult(err);
405                                         // do not set errors.. that's not done here..
406                                         return true;
407                                 }
408                                 errors.set(line, errmsg); // depricated - this is used by the editor currently -- but we are planning to switch from that..
409                                 print("got  errors\n");
410                                 return true;
411
412                         }
413                         // now syntax is OK.. try the 
414                         
415                         
416                         
417                         if (ptype == "file") {
418                                  return this.javascriptHasCompressionErrors(file, state, code);
419                         }
420                         print("no errors\n");
421                         return false;
422                           
423                 } 
424                 
425                 public bool  javascriptHasCompressionErrors(JsRender.JsRender file, WindowState state, string code)
426                 {
427                         // this uses the roojspacker code to try and compress the code.
428                         // it should highlight errors before we actually push live the code.
429                         
430                         // standard error format:  file %s, line %s, Error 
431
432                         var p = new JSDOC.Packer();
433                         p.keepWhite = false;
434                         p.skipScope = false;
435                         p.dumpTokens = false;
436                         p.cleanup = false; 
437                  
438                          
439                         p.packFile(code, file.path,"");
440                         state.showCompileResult(p.result);
441                         if (p.hasErrors()) {
442                                 return true;
443                         }
444                         return false;
445                         
446
447                 
448                 }
449                 
450                 
451                       
452                 public abstract void fillPack(JsRender.Node node,JsRender.Node parent);
453                 public abstract void load();
454                 public abstract Gee.HashMap<string,GirObject> getPropertiesFor(string ename, string type);
455                 public abstract GirObject? getClass(string ename);
456         
457                 public abstract bool typeOptions(string fqn, string key, string type, out string[] opts);
458                 public abstract  List<SourceCompletionItem> suggestComplete(
459                                 JsRender.JsRender file,
460                                 JsRender.Node? node,
461                                 string proptype, 
462                                 string key,
463                                 string complete_string
464                 );
465         }
466
467
468 }
469
470
471