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