fix line numbering issues with vala generator - hopefully fixes completion in node...
[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  * 
14  */
15
16 namespace Palete {
17         
18         public errordomain ValaSourceError {
19                 INVALID_FORMAT 
20         }
21         
22         //public delegate  void ValaSourceResult(Json.Object res);
23         
24          
25
26         public class ValaSourceOLD : Object {
27  
28                 public Json.Object? last_result = null;
29                 public signal void compiled(Json.Object res);
30                 public signal void compile_output(string str);
31  
32                 
33                 public JsRender.JsRender file;
34                 public int line_offset = 0;
35                  
36                 public Gee.ArrayList<Spawn> children;
37                 Spawn compiler;
38                 
39                 public string tmpfile_path = "";
40                 
41                 
42                 public int terminal_pid = 0;
43                 
44                 public ValaSourceOLD(   ) 
45                 {
46                         base();
47                          
48                         this.compiler = null;
49                         this.children = new Gee.ArrayList<Spawn>();
50                         
51                 }
52                 public void dumpCode(string str) 
53                 {
54                         var ls = str.split("\n");
55                         for (var i=0;i < ls.length; i++) {
56                                 print("%d : %s\n", i+1, ls[i]);
57                         }
58                 }
59                 
60                 //public Gee.HashMap<int,string> checkFile()
61                 //{
62                 //      return this.checkString(JsRender.NodeToVala.mungeFile(this.file));
63                 //}
64
65                 public bool checkFileWithNodePropChange(
66                   
67                                         JsRender.JsRender file,
68                                         JsRender.Node node, 
69                                         JsRender.NodeProp prop,
70                                         string val
71                                  )
72                 {
73                         this.file = file;
74                         
75                         if (this.compiler != null) {
76                                 //this.compiler.tidyup();
77                                 //this.spawnResult(0,"","");
78                                 return false;
79                         }
80                         
81                         
82                         // untill we get a smarter renderer..
83                         // we have some scenarios where changing the value does not work
84                         if (prop.name == "xns" || prop.name == "xtype") {
85                                 return  false;
86                         }
87                                 
88                          
89                         var old = prop.val;
90                         
91
92                         prop.val =  "/*--VALACHECK-START--*/ " + prop.val ;
93                         
94
95                         var tmpstring = JsRender.NodeToVala.mungeFile(file);
96                         prop.val = old;
97                         
98                         //print("%s\n", tmpstring);
99                         var bits = tmpstring.split("/*--VALACHECK-START--*/");
100                         var offset =0;
101                         if (bits.length > 0) {
102                                 offset = bits[0].split("\n").length +1;
103                         }
104                         
105                         this.line_offset = offset;
106                         
107                         //this.dumpCode(tmpstring);
108                         //print("offset %d\n", offset);
109                         return this.checkStringSpawn(tmpstring );
110                         
111                         // modify report
112                         
113                         
114                         
115                 }
116                 
117                  
118                 private bool checkStringSpawn( string contents  )
119                 {
120                         
121                         if (this.compiler != null) {
122                                 this.compiler.isZombie();
123                                 //this.compiler.tidyup();
124                                 //this.spawnResult(-2,"","");
125                                 return false;
126                         }
127                         var pr = (Project.Gtk)(file.project);
128                         
129                         var tmpfilename = pr.path + "/build/tmp-%u.vala".printf( (uint) GLib.get_real_time()) ;
130                         try {
131                                 GLib.FileUtils.set_contents(tmpfilename,contents);
132                         } catch (GLib.FileError e) {
133                                 GLib.debug("Error creating temp build file %s : %s", tmpfilename, e.message);
134                                 return false;
135                         }
136                          
137
138                  
139                         var valafn = "";
140                         try {             
141                            var  regex = new Regex("\\.bjs$");
142                         
143                                 valafn = regex.replace(this.file.path,this.file.path.length , 0 , ".vala");
144                          } catch (GLib.RegexError e) {
145                                  
146                             return false;
147                         }   
148                         
149
150                         
151                         string[] args = {};
152                         args += BuilderApplication._self;
153                         args += "--skip-linking";
154                         args += "--project";
155                         args += this.file.project.path;
156                         args += "--target";
157                         args +=  pr.firstBuildModuleWith(this.file);
158                         args += "--add-file";
159                         args +=  tmpfilename;
160                         args += "--skip-file";
161                         args += valafn;
162                         
163                         this.tmpfile_path = tmpfilename;
164                         try {
165                                 this.compiler = new Spawn(pr.path + "/build", args);
166                         } catch (GLib.Error e) {
167                                 GLib.debug("Spawn failed: %s", e.message);
168                                 return false;
169                         }
170                         this.compiler.complete.connect(spawnResult);
171                 this.spinner(true);
172                         try {
173                                 this.compiler.run(); 
174                         } catch (GLib.Error e) {
175                                 GLib.debug("Error %s",e.message);
176                                 this.spinner(false);
177                                 this.compiler = null;
178                                 this.deleteTemp();
179                                 return false;
180
181                         }
182                         return true;
183                          
184                 }
185                 
186                 public void spinner(bool state)
187                 {
188                         foreach (var win in BuilderApplication.windows) {
189                                 if (state) {
190                                         win.statusbar_compile_spinner.start();
191                                 }  else {
192                                         win.statusbar_compile_spinner.stop();
193                                 }
194                         }
195                 }
196                 
197                 
198                 public bool checkFileSpawn(JsRender.JsRender file )
199                 {
200                         // race condition..
201                         if (this.compiler != null) { 
202                                 this.compiler.isZombie();
203                                 //this.compiler.tidyup();
204                                 //this.spawnResult(-2,"","");
205                                 return false;
206                         }
207                         
208                         this.file = file;
209                         var pr = (Project.Gtk)(file.project);
210                         this.line_offset = 0;
211                           
212                         string[] args = {};
213                         args += BuilderApplication._self;
214                         args += "--skip-linking";
215                         args += "--project";
216                         args += this.file.project.path;
217                         args += "--target";
218                         args += pr.firstBuildModuleWith(this.file);
219                          
220                           
221                          
222                         
223                         
224                         try {
225                             this.compiler = new Spawn(pr.path+"/build", args);
226                             this.compiler.output_line.connect(this.compile_output_line);
227                             this.compiler.complete.connect(spawnResult);
228                         this.spinner(true);
229                             this.compiler.run(); 
230                         
231                          
232                         } catch (GLib.Error e) {
233                             GLib.debug(e.message);
234                         this.spinner(false);
235                             this.compiler = null;
236                             return false;
237                         }
238                         return true;
239                          
240                 }
241                 
242  
243
244                 
245                 
246                 public void spawnExecute(JsRender.JsRender file)
247                 {
248                         // race condition..
249                         if (this.compiler != null) {
250                                 this.compiler.isZombie();
251                                 this.compiler.tidyup();
252                                 this.spawnResult(-2,"","");
253                                 return;
254                         }
255                         if (!(file.project is Project.Gtk)) {
256                             return;
257                 }
258                         var pr = (Project.Gtk)(file.project);
259                         
260                         
261                         this.file = file;
262                         this.line_offset = 0;
263                         
264
265                           
266                         string[] args = {};
267                         args += BuilderApplication._self;
268                         args += "--debug";
269                         args += "all";
270                         
271                         args += "--project";
272                         args += this.file.project.path;
273                         args += "--target";
274                         args += pr.firstBuildModuleWith(this.file); 
275                         
276                         //args += "--output"; -- set up by the module -- defaults to testrun
277                         //args += "/tmp/testrun";
278                         
279                         // assume code is in home...
280                         try {
281                             this.compiler = new Spawn( GLib.Environment.get_home_dir(), args);
282                             this.compiler.output_line.connect(this.compile_output_line);
283                             this.compiler.complete.connect(runResult);
284                         this.spinner(true);
285                             this.compiler.run(); 
286                                 this.children.add(this.compiler); //keep a reference...
287                          
288                         } catch (GLib.Error e) {
289                         this.spinner(false);
290                             GLib.debug(e.message);
291                             this.compiler = null;
292
293                         }
294                         return;
295                          
296                 }
297                 public void compile_output_line(   string str )
298                 {
299                         GLib.debug("%s", str);
300                         this.compile_output(str);
301                 }
302                 /**
303                 * Used to compile a non builder file..
304                 */
305                  
306                  
307                 public bool checkPlainFileSpawn( JsRender.JsRender file, string contents )
308  
309                 {
310                         // race condition..
311                         if (this.compiler != null) { 
312                                 this.compiler.isZombie();
313                                 return false;
314                         }
315                         this.file = file;
316             
317                         var pr = (Project.Gtk)(file.project);
318                         
319                         var m = pr.firstBuildModuleWith(file);
320                         var cg = pr.compilegroups.get(m);
321
322                         if (cg == null) {
323                           return false;
324                         }
325                         var foundit = false;
326                         
327             if (cg.sources == null) {
328                 return false;
329             }
330             for (var i = 0; i < cg.sources.size; i++) {
331                             var path =  pr.path + "/" + cg.sources.get(i);
332                     if (path == file.path) {
333                         foundit = true;
334                         break;
335                                 }
336                         }
337
338                         if (!foundit) {
339                           
340                             this.compiler = null;
341                         
342                             return false; // do not run the compile..
343                         }
344                         // is the file in the module?
345                         
346                         var tmpfilename = pr.path + "/build/tmp-%u.vala".printf( (uint) GLib.get_real_time()) ;
347                         try {
348                                 GLib.FileUtils.set_contents(tmpfilename,contents);
349                         } catch (GLib.FileError e) {
350                                 GLib.debug("Error creating temp build file %s : %s", tmpfilename, e.message);
351                                 return false;
352                         }
353                          
354                         var target = pr.firstBuildModule();
355                         if (target.length < 1) {
356                                 return false;
357                         }
358                         
359                         // this.file = null; << /why
360                         this.line_offset = 0;
361                           
362                         string[] args = {};
363                         args += BuilderApplication._self;
364                         args += "--skip-linking";
365                         args += "--project";
366                         args +=  file.project.path;
367                         args += "--target";
368  
369                         args += pr.firstBuildModuleWith(this.file);
370                         args += "--add-file";
371                         args +=  tmpfilename;
372                         args += "--skip-file";
373                         args += file.path;
374                          
375                         this.tmpfile_path = tmpfilename;
376                         
377                         
378                         try {
379                             this.compiler = new Spawn("/tmp", args);
380                                 this.compiler.output_line.connect(this.compile_output_line);
381                             this.compiler.complete.connect(spawnResult);
382                         this.spinner(true);
383                             this.compiler.run(); 
384                         } catch (GLib.Error e) {
385                         this.spinner(false);
386                             this.compiler = null;
387                             this.deleteTemp();
388                                 
389                             
390                             return false;
391                         }
392                         return true;
393                          
394                 }
395                 
396                 public void deleteTemp()
397                 {
398                          if (this.tmpfile_path == "") {
399                                 return;
400                         }
401                         if (GLib.FileUtils.test(this.tmpfile_path, GLib.FileTest.EXISTS)) {
402                                 GLib.FileUtils.unlink(this.tmpfile_path);
403                         }
404                         var cf = this.tmpfile_path.substring(0, this.tmpfile_path.length-4) + "c";
405                         GLib.debug("try remove %s",cf);
406                         if (GLib.FileUtils.test(cf, GLib.FileTest.EXISTS)) {
407                                 GLib.FileUtils.unlink(cf);
408                         }
409                         var ccf = GLib.Path.get_dirname(cf) + "/build/" + GLib.Path.get_basename(cf);
410                         GLib.debug("try remove %s",ccf);
411                         if (GLib.FileUtils.test(ccf, GLib.FileTest.EXISTS)) {
412                                 GLib.FileUtils.unlink(ccf);
413                         }
414                         this.tmpfile_path = "";
415                 }
416                 // update the compiler results into the lists.
417                 
418                 
419                 // what to do when we have finished running..
420                 // call this.compiled(result) (handled by windowstate?) 
421                 public void spawnResult(int res, string output, string stderr)
422                 {
423                          
424                         if (res == -2) {
425                                 var ret = new Json.Object();
426                                 ret.set_boolean_member("success", false);
427                                 ret.set_string_member("message","killed");
428                                 this.compiled(ret);
429                                 this.compiler.isZombie();
430                                 this.compiler = null;
431                                 this.deleteTemp();
432                             this.spinner(false);
433                             return;
434                         }
435                         try { 
436                                 //GLib.debug("GOT output %s", output);
437                                 
438                                 var pa = new Json.Parser();
439                                 pa.load_from_data(output);
440                                 var node = pa.get_root();
441
442                                 if (node.get_node_type () != Json.NodeType.OBJECT) {
443                                         var ret = new Json.Object();
444                                         ret.set_boolean_member("success", false);
445                                         ret.set_string_member("message", 
446                                                 "Compiler returned Unexpected element type %s".printf( 
447                                                         node.type_name ()
448                                                 )
449                                         );
450                                         this.compiled(ret);
451                                         this.compiler = null;
452                                 }
453                                 var ret = node.get_object ();
454                                 ret.set_int_member("line_offset", this.line_offset);
455                                 this.last_result = ret;
456                                 this.compiled(ret);
457                                 
458                                 
459                         } catch (GLib.Error e) {
460                                 var ret = new Json.Object();
461                                 ret.set_boolean_member("success", false);
462                                 ret.set_string_member("message", e.message);
463                                 this.compiled(ret);
464                         }
465                         this.compiler.isZombie();
466                         this.compiler = null;
467                         this.deleteTemp();
468                 this.spinner(false);                    
469                         //compiler.unref();
470                         //tmpfile.unref();
471                          
472                         
473                         
474                 }
475                 
476                 public void killChildren(int pid)
477                 {
478                         if (pid < 1) {
479                                 return;
480                         }
481                         var cn = "/proc/%d/task/%d/children".printf(pid,pid);
482                         if (!FileUtils.test(cn, GLib.FileTest.EXISTS)) {
483                                 GLib.debug("%s doesnt exist - killing %d", cn, pid);
484                                 Posix.kill(pid, 9);
485                                 return;
486                         }
487                         string cpids = "";
488                         try {
489                                 FileUtils.get_contents(cn, out cpids);
490                         
491
492                                 if (cpids.length > 0) {
493                                         this.killChildren(int.parse(cpids));
494                                 }
495
496                         } catch (GLib.FileError e) {
497                                 // skip
498                         }
499                         GLib.debug("killing %d", pid);  
500                         Posix.kill(pid, 9);
501                 }
502                 
503                 
504                 public void runResult(int res, string output, string stderr)
505                 {
506                         this.compiler = null;
507                         
508                 
509                         GLib.debug("run result last pid = %d", this.terminal_pid );
510                 this.spinner(false);            
511                         this.killChildren(this.terminal_pid);
512                         this.terminal_pid = 0;
513                          
514                         
515                         
516                         
517                         
518                         var mod = "";
519                         var pr = (Project.Gtk)(this.file.project);
520                         
521                         
522                         
523                         if (this.file.build_module.length > 0 ) {
524                     mod =  this.file.build_module;
525                         } else {
526                             mod =  pr.firstBuildModule();
527                         }
528                         if (mod.length < 1) {
529                                 GLib.debug("missing compilegroup module");
530                                 return;
531                         }
532                         var cg =  pr.compilegroups.get(mod);
533                         var exe = pr.path + "/build/" + cg.name;
534                         
535                         
536                         
537                         if (!GLib.FileUtils.test(exe, GLib.FileTest.EXISTS)) {
538                                 print("Missing output file: %s\n",exe);
539                                 return;
540                         }
541                         var gdb_cfg= pr.path + "/build/.gdb-script";
542                         if (!GLib.FileUtils.test(gdb_cfg, GLib.FileTest.EXISTS)) {
543                                 pr.writeFile("build/.gdb-script", "set debuginfod enabled off\nr");
544                         }
545                         
546                         
547                         
548                          string[] args = "/usr/bin/gnome-terminal --disable-factory --wait -- /usr/bin/gdb -x".split(" ");
549                         //string[] args = "/usr/bin/xterm  -e /usr/bin/gdb -x".split(" ");
550                  
551                         args+= gdb_cfg;
552
553                         
554                         // runs gnome-terminal, with gdb .. running the application..
555                         // fixme -- need a system/which
556                         
557                         args += exe;
558                         if (cg.execute_args.length > 0) {
559                                 args+= "--args";
560                                 var aa = cg.execute_args.split(" ");
561                                 for (var i =0; i < aa.length; i++) {
562                                         args += aa[i];
563                                 }
564                         }
565
566                     print("OUT: %s\n\n----\nERR:%s\n", output, stderr);
567                     
568                     // should be home directory...
569                     
570                     
571                     try {
572                     
573                         var exec = new Spawn(pr.path , args);
574                         exec.env = GLib.Environ.get();
575                         /*{ 
576                                 "PATH=" + GLib.Environment.get_variable("PATH"),
577                                 "SHELL=" + GLib.Environment.get_variable("SHELL"),
578                                 "DISPLAY=" + GLib.Environment.get_variable("DISPLAY"),
579                                 "TERM=xterm",
580                                 "USER=" + GLib.Environment.get_variable("USER"),
581                                 "DBUS_SESSION_BUS_ADDRESS="+ GLib.Environment.get_variable("DBUS_SESSION_BUS_ADDRESS"),
582                                 "XDG_SESSION_PATH="+ GLib.Environment.get_variable("XDG_SESSION_PATH"),
583                                         "SESSION_MANAGER="+ GLib.Environment.get_variable("SESSION_MANAGER"),
584                                         "XDG_SESSION_CLASS="+ GLib.Environment.get_variable("XDG_SESSION_CLASS"),
585                                         "XDG_SESSION_DESKTOP="+ GLib.Environment.get_variable("XDG_SESSION_DESKTOP"),
586                                         "XDG_SESSION_TYPE="+ GLib.Environment.get_variable("XDG_SESSION_TYPE")
587                                 };
588                                 */
589                         exec.detach = true;
590                                 exec.run(); 
591
592                                 this.terminal_pid = exec.pid;
593                                 GLib.debug("Child PID = %d", this.terminal_pid);
594                                 
595                     } catch(GLib.Error e) {
596                                 GLib.debug("Failed to spawn: %s", e.message);
597                                 return;
598                         }
599                         
600                 }
601         }
602                  
603 }
604 /*
605 int main (string[] args) {
606
607         var a = new ValaSource(file);
608         a.create_valac_tree();
609         return 0;
610 }
611 */
612
613