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