Fix #7250 - better handling of adding properties
[roobuilder] / src / Palete / ValaSource.vala
1
2 // valac TreeBuilder.vala --pkg libvala-0.24 --pkg posix -o /tmp/treebuilder
3
4 /**
5  * 
6  *  This just deals with spawning the compiler and getting the results.
7  * 
8  *  each window should have one of these...
9  * 
10  *  x = new ValaSource();
11  *  x.connect.compiled(... do something with results... );
12  *  
13  * x.
14  * 
15  */
16
17 namespace Palete {
18         
19         public errordomain ValaSourceError {
20                 INVALID_FORMAT 
21         }
22         
23         //public delegate  void ValaSourceResult(Json.Object res);
24         
25          
26
27         public class ValaSource : Object {
28  
29                 
30                 public signal void compiled(Json.Object res);
31                 public signal void compile_output(string str);
32                 public Xcls_MainWindow window;
33                 
34                 JsRender.JsRender file;
35                 public int line_offset = 0;
36                 
37                 public Gee.ArrayList<Spawn> children;
38                 public ValaSource( Xcls_MainWindow window ) 
39                 {
40                         base();
41                         this.window  = window;
42                         this.compiler = null;
43                         this.children = new Gee.ArrayList<Spawn>();
44                         
45                 }
46                 public void dumpCode(string str) 
47                 {
48                         var ls = str.split("\n");
49                         for (var i=0;i < ls.length; i++) {
50                                 print("%d : %s\n", i+1, ls[i]);
51                         }
52                 }
53                 
54                 //public Gee.HashMap<int,string> checkFile()
55                 //{
56                 //      return this.checkString(JsRender.NodeToVala.mungeFile(this.file));
57                 //}
58
59                 public bool checkFileWithNodePropChange(
60                   
61                                         JsRender.JsRender file,
62                                         JsRender.Node node, 
63                                         JsRender.NodeProp prop,
64                                         string val
65                                  )
66                 {
67                         this.file = file;
68                         
69                         if (this.compiler != null) {
70                                 return false;
71                         }
72                         
73                          
74                         var hash = prop.ptype == JsRender.NodePropType.LISTENER ? node.listeners : node.props;
75                         
76                         // untill we get a smarter renderer..
77                         // we have some scenarios where changing the value does not work
78                         if (prop.name == "xns" || prop.name == "xtype") {
79                                 return  false;
80                         }
81                                 
82                          
83                         var old = prop.val;
84                         
85
86                         prop.val =  "/*--VALACHECK-START--*/ " + prop.val ;
87                         
88
89                         var tmpstring = JsRender.NodeToVala.mungeFile(file);
90                         prop.val = old;
91                         
92                         //print("%s\n", tmpstring);
93                         var bits = tmpstring.split("/*--VALACHECK-START--*/");
94                         var offset =0;
95                         if (bits.length > 0) {
96                                 offset = bits[0].split("\n").length +1;
97                         }
98                         
99                         this.line_offset = offset;
100                         
101                         //this.dumpCode(tmpstring);
102                         //print("offset %d\n", offset);
103                         return this.checkStringSpawn(tmpstring );
104                         
105                         // modify report
106                         
107                         
108                         
109                 }
110                 Spawn compiler;
111                  
112                 public bool checkStringSpawn(
113                                 string contents 
114                         )
115                 {
116                         
117                         if (this.compiler != null) {
118                                 return false;
119                         }
120                         
121                         FileIOStream iostream;
122                         var tmpfile = File.new_tmp ("test-XXXXXX.vala", out iostream);
123                         tmpfile.ref();
124
125                         OutputStream ostream = iostream.output_stream;
126                         DataOutputStream dostream = new DataOutputStream (ostream);
127                         dostream.put_string (contents);
128                         
129                         var valafn = "";
130                         try {             
131                            var  regex = new Regex("\\.bjs$");
132                         
133                                 valafn = regex.replace(this.file.path,this.file.path.length , 0 , ".vala");
134                          } catch (GLib.RegexError e) {
135                                  
136                             return false;
137                         }   
138                         
139                         string[] args = {};
140                         args += BuilderApplication._self;
141                         args += "--project";
142                         args += this.file.project.fn;
143                         args += "--target";
144                         args += this.file.build_module;
145                         args += "--add-file";
146                         args +=  tmpfile.get_path();
147                         args += "--skip-file";
148                         args += valafn;
149                         
150                          
151                         
152                         this.compiler = new Spawn("/tmp", args);
153                         this.compiler.complete.connect(spawnResult);
154                         this.window.statusbar_compile_spinner.start();
155                         try {
156                                 this.compiler.run(); 
157                         } catch (GLib.SpawnError e) {
158                                 GLib.debug(e.message);
159                                 this.window.statusbar_compile_spinner.stop();
160                                 this.compiler = null;
161                                 return false;
162
163                         }
164                         return true;
165                          
166                 }
167                 
168                 public bool checkFileSpawn(JsRender.JsRender file )
169                 {
170                         // race condition..
171                         if (this.compiler != null) { 
172                                 return false;
173                         }
174                         
175                         this.file = file;
176                         this.line_offset = 0;
177                           
178                         string[] args = {};
179                         args += BuilderApplication._self;
180                         args += "--project";
181                         args += this.file.project.fn;
182                         args += "--target";
183                         args += this.file.build_module;
184                          
185                          
186                         
187                         
188                         try {
189                             this.compiler = new Spawn("/tmp", args);
190                             this.compiler.complete.connect(spawnResult);
191                                 this.window.statusbar_compile_spinner.start();
192                             this.compiler.run(); 
193                         
194                          
195                         } catch (GLib.Error e) {
196                             GLib.debug(e.message);
197                             this.window.statusbar_compile_spinner.stop();
198                             this.compiler = null;
199                             return false;
200                         }
201                         return true;
202                          
203                 }
204                 
205  
206
207                 
208                 
209                 public void spawnExecute(JsRender.JsRender file)
210                 {
211                         // race condition..
212                         if (this.compiler != null) { 
213                                 return;
214                         }
215                         if (!(file.project is Project.Gtk)) {
216                             return;
217                         }
218                         var pr = (Project.Gtk)(file.project);
219                         
220                         
221                         this.file = file;
222                         this.line_offset = 0;
223                           
224                         string[] args = {};
225                         args += BuilderApplication._self;
226                         args += "--project";
227                         args += this.file.project.fn;
228                         args += "--target";
229                         if (this.file.build_module.length > 0 ) {
230                             args += this.file.build_module;
231                         } else {
232                             args += pr.firstBuildModule();
233                         }
234                         //args += "--output"; -- set up by the module -- defaults to testrun
235                         //args += "/tmp/testrun";
236                         
237                         // assume code is in home...
238                         try {
239                             this.compiler = new Spawn( GLib.Environment.get_home_dir(), args);
240                             this.compiler.output_line.connect(compile_output_line);
241                             this.compiler.complete.connect(runResult);
242                             this.window.statusbar_compile_spinner.start();
243                             this.compiler.run(); 
244                                 this.children.add(this.compiler); //keep a reference...
245                          
246                         } catch (GLib.Error e) {
247                                 this.window.statusbar_compile_spinner.stop();
248                             GLib.debug(e.message);
249                             this.compiler = null;
250
251                         }
252                         return;
253                          
254                 }
255                 public void compile_output_line(   string str )
256                 {
257                         this.compile_output(str);
258                 }
259                 /**
260                 * Used to compile a non builder file..
261                 */
262                  
263                  
264                 public bool checkPlainFileSpawn( JsRender.JsRender file, string contents )
265  
266                 {
267                         // race condition..
268                         if (this.compiler != null) { 
269                                 return false;
270                         }
271             
272                         var pr = (Project.Gtk)(file.project);
273                         
274                         var m = pr.firstBuildModule();
275                         var cg = pr.compilegroups.get(m);
276
277                         if (cg == null) {
278                           return false;
279                         }
280                         var foundit = false;
281                         
282             if (cg.sources == null) {
283                 return false;
284             }
285             for (var i = 0; i < cg.sources.size; i++) {
286                             var path = pr.resolve_path(
287                                     pr.resolve_path_combine_path(pr.firstPath(),cg.sources.get(i)));
288                             if (path == file.path) {
289                                 foundit = true;
290                                 break;
291                                         }
292                         }
293
294                         if (!foundit) {
295                           
296                             this.compiler = null;
297                         
298                             return false; // do not run the compile..
299                         }
300                         // is the file in the module?
301                         
302                         
303                         FileIOStream iostream;
304                         var tmpfile = File.new_tmp ("test-XXXXXX.vala", out iostream);
305                         tmpfile.ref();
306
307                         OutputStream ostream = iostream.output_stream;
308                         DataOutputStream dostream = new DataOutputStream (ostream);
309                         dostream.put_string (contents);
310                         
311                         var target = pr.firstBuildModule();
312                         if (target.length < 1) {
313                                 return false;
314                         }
315                         
316                         this.file = null;
317                         this.line_offset = 0;
318                           
319                         string[] args = {};
320                         args += BuilderApplication._self;
321                         args += "--project";
322                         args +=  file.project.fn;
323                         args += "--target";
324  
325                         args += pr.firstBuildModule();
326                         args += "--add-file";
327                         args +=  tmpfile.get_path();
328                         args += "--skip-file";
329                         args += file.path;
330                          
331                         
332                         
333                         
334                         try {
335                             this.compiler = new Spawn("/tmp", args);
336                             this.compiler.complete.connect(spawnResult);
337                             this.window.statusbar_compile_spinner.start();
338                             this.compiler.run(); 
339                         } catch (GLib.Error e) {
340                             this.window.statusbar_compile_spinner.stop();
341                             this.compiler = null;
342                             return false;
343                         }
344                         return true;
345                          
346                 }
347                  
348                 
349                 public void spawnResult(int res, string output, string stderr)
350                 {
351                          
352                         this.window.statusbar_compile_spinner.stop();   
353                         try { 
354                                 //GLib.debug("GOT output %s", output);
355                                 
356                                 var pa = new Json.Parser();
357                                 pa.load_from_data(output);
358                                 var node = pa.get_root();
359
360                                 if (node.get_node_type () != Json.NodeType.OBJECT) {
361                                         var ret = new Json.Object();
362                                         ret.set_boolean_member("success", false);
363                                         ret.set_string_member("message", 
364                                                 "Compiler returned Unexpected element type %s".printf( 
365                                                         node.type_name ()
366                                                 )
367                                         );
368                                         this.compiled(ret);
369                                         this.compiler = null;
370                                 }
371                                 var ret = node.get_object ();
372                                 ret.set_int_member("line_offset", this.line_offset);
373                                 
374                                 this.compiled(ret);
375                                 
376                                 
377                         } catch (GLib.Error e) {
378                                 var ret = new Json.Object();
379                                 ret.set_boolean_member("success", false);
380                                 ret.set_string_member("message", e.message);
381                                 this.compiled(ret);
382                         }
383                         this.compiler = null;
384                         //compiler.unref();
385                         //tmpfile.unref();
386                          
387                         
388                         
389                 }
390                 
391                 public void runResult(int res, string output, string stderr)
392                 {
393                         this.compiler = null;
394                         var exe = "/tmp/testrun";
395                         var mod = "";
396                         var pr = (Project.Gtk)(this.file.project);
397                         
398                         
399                         
400                         if (this.file.build_module.length > 0 ) {
401                     mod =  this.file.build_module;
402                         } else {
403                             mod =  pr.firstBuildModule();
404                         }
405                         if (mod.length < 1) {
406                                 return;
407                         }
408                         var cg =  pr.compilegroups.get(mod);
409                         if (cg.target_bin.length > 0) {
410                                 exe = cg.target_bin;
411                         }
412                         
413                         
414                         if (!GLib.FileUtils.test(exe, GLib.FileTest.EXISTS)) {
415                                 print("Missing output file: %s\n",exe);
416                                 return;
417                         }
418                         string[] args = "/usr/bin/gnome-terminal -x /usr/bin/gdb -ex=r --args".split(" ");
419
420                         
421                         // runs gnome-terminal, with gdb .. running the application..
422                         // fixme -- need a system/which
423                         
424                         args += exe;
425                         if (cg.execute_args.length > 0) {
426                                 var aa = cg.execute_args.split(" ");
427                                 for (var i =0; i < aa.length; i++) {
428                                         args += aa[i];
429                                 }
430                         }
431
432                     print("OUT: %s\n\n----\nERR:%s\n", output, stderr);
433                     
434                     // should be home directory...
435                     
436                     
437                     
438             var exec = new Spawn(GLib.Environment.get_home_dir() , args);
439             exec.detach = true;
440                     exec.run(); 
441                         
442                 }
443         }
444                  
445 }
446 /*
447 int main (string[] args) {
448
449         var a = new ValaSource(file);
450         a.create_valac_tree();
451         return 0;
452 }
453 */
454
455