fix line numbering issues with vala generator - hopefully fixes completion in node...
[roobuilder] / src / Palete / ValaCompileRequest.vala
1
2
3
4 namespace Palete {
5         public enum ValaCompileRequestType {
6                 PROP_CHANGE,
7                 FILE_CHANGE,
8                 PROJECT,
9                 RUN
10         }
11                 
12         public class ValaCompileRequest  : Object
13         {
14                 ValaCompileRequestType requestType;
15                 
16                 public JsRender.JsRender? file = null;
17                 JsRender.Node? node = null;
18                 JsRender.NodeProp? prop = null;
19                 string alt_code = "";
20                 string tmpfile = "";
21                 Spawn? compiler  = null;
22         ///     ValaCompileQueue? queue = null;
23  
24                 
25         
26                 public Gee.HashMap<string,GLib.ListStore>? errorByType = null;
27                 public Gee.HashMap<string,GLib.ListStore>? errorByFile  = null;
28                         
29         
30                 public ValaCompileRequest (
31                         ValaCompileRequestType requestType,
32                         JsRender.JsRender file ,
33                         JsRender.Node? node,
34                         JsRender.NodeProp? prop,
35                         string alt_code = ""
36                          
37                 ) {
38                         this.requestType = requestType;
39                         this.file = file;
40                         this.node = node;
41                         this.prop = prop;
42                         this.alt_code = alt_code;
43                 }
44                 public bool eq(ValaCompileRequest c) {
45                         var neq = false;
46                         if (this.node == null && c.node == null) {
47                                 neq = true;
48                         } else if (this.node == null || c.node == null) {
49                                 neq = false;
50                         } else {
51                                 neq = this.node.oid == c.node.oid ;
52                         }
53                         
54                         var peq = false;                        
55                         if (this.prop == null && c.prop == null) {
56                                 peq = true;
57                         } else if (this.prop == null || c.prop == null) {
58                                 peq = false;
59                         } else {
60                                 peq = this.prop.name == c.prop.name ;
61                         }
62
63                         
64                         return 
65                                 this.requestType == c.requestType &&
66                                 this.file.path == c.file.path &&
67                                 neq && peq &&
68                                 this.alt_code == c.alt_code;
69                                 
70                                 
71                 
72                 }
73                 public string target()
74                 {
75                         var pr = (Project.Gtk) this.file.project;
76                         return pr.firstBuildModuleWith(this.file);
77                 
78                 }
79                 
80                 string generateTempContents() {
81                 
82                         var oldcode  = "";
83                         var contents = this.alt_code;
84                         if (this.requestType == ValaCompileRequestType.PROP_CHANGE) {
85                                 oldcode  = this.prop.val;
86                                 this.prop.val = this.alt_code;
87                                 contents = this.file.toSourceCode();
88                                 this.prop.val = oldcode;
89                         }
90                         return contents;
91                 }
92                 
93                 
94                 bool generateTempFile() {
95                  
96                         var contents = this.generateTempContents();
97                          
98                         var pr = this.file.project;
99                         
100                         this.tmpfile = pr.path + "/build/tmp-%u.vala".printf( (uint) GLib.get_real_time()) ;
101                         try {
102                                 GLib.FileUtils.set_contents(this.tmpfile,contents);
103                         } catch (GLib.FileError e) {
104                                 GLib.debug("Error creating temp build file %s : %s", tmpfile, e.message);
105                                 return false;
106                         }
107                         return true;
108                 }
109                 
110                 public bool run()
111                 {
112                         //this.queue = queue;
113                         if ( this.target() == "") {
114                                 GLib.debug("missing target");
115                                 this.onCompileFail();
116
117                                 return false;
118                         }
119                         string[] args = {};
120                         args += BuilderApplication._self;
121                         if (this.requestType != ValaCompileRequestType.RUN) {
122                                 args += "--skip-linking";
123                         }
124                         args += "--project";
125                         args += this.file.project.path;
126                         args += "--target";
127                         args +=  this.target();
128                         if  (this.requestType == ValaCompileRequestType.PROP_CHANGE || this.requestType == ValaCompileRequestType.FILE_CHANGE) {
129                                 
130                                 if (!this.generateTempFile()) {
131                                         GLib.debug("failed to make temp file");
132                                         this.onCompileFail();
133                                         return false;
134                                 }
135                                 args += "--add-file";
136                                 args +=  this.tmpfile;
137                                 args += "--skip-file";
138                                 args += this.file.targetName(); // ?? bjs???
139                         }
140                         var pr = (Project.Gtk)(file.project);
141                         try {
142                                 pr.makeProjectSubdir("build");
143                                 this.compiler = new Spawn(pr.path + "/build", args);
144                         } catch (GLib.Error e) {
145                                 GLib.debug("Spawn failed: %s", e.message);
146
147                                 this.onCompileFail();
148                                 return false;
149                         }
150                     this.compiler.output_line.connect(this.onOutput);
151                         this.compiler.complete.connect(this.onCompileComplete);
152                         try {
153                                 this.compiler.run(); 
154                         } catch (GLib.Error e) {
155                                 GLib.debug("Spawn error %s", e.message);
156                                 this.onCompileFail();
157                                 return false;
158                         }
159                         return true; // it's running..
160                 }
161                 void onCompileFail() // only called before we start (assumes spinner has nto started etc..
162                 {
163                         this.compiler = null;
164                         this.deleteTemp();
165                 }
166                 
167                 public void cancel() {
168                         Posix.kill(this.compiler.pid, 9);
169                         this.compiler = null;
170                         this.deleteTemp();
171                 }
172                 
173                 public void deleteTemp()
174                 {
175                          if (this.tmpfile == "") {
176                                 return;
177                         }
178                         if (GLib.FileUtils.test(this.tmpfile, GLib.FileTest.EXISTS)) {
179                                 GLib.FileUtils.unlink(this.tmpfile);
180                         }
181                         var cf = this.tmpfile.substring(0, this.tmpfile.length-4) + "c";
182                         GLib.debug("try remove %s",cf);
183                         if (GLib.FileUtils.test(cf, GLib.FileTest.EXISTS)) {
184                                 GLib.FileUtils.unlink(cf);
185                         }
186                         var ccf = GLib.Path.get_dirname(cf) + "/build/" + GLib.Path.get_basename(cf);
187                         GLib.debug("try remove %s",ccf);
188                         if (GLib.FileUtils.test(ccf, GLib.FileTest.EXISTS)) {
189                                 GLib.FileUtils.unlink(ccf);
190                         }
191                         this.tmpfile = "";
192                 }
193                 public void onCompileComplete(int res, string output, string stderr) 
194                 {
195                         this.deleteTemp();
196                         this.compiler.isZombie();
197                         GLib.debug("compile got %s", output);
198                         if (output == "") {
199                                 BuilderApplication.showSpinner(false);
200                                 return;
201                         }
202                         
203                         try { 
204                                 //GLib.debug("GOT output %s", output);
205                                 
206                                 var pa = new Json.Parser();
207                                 pa.load_from_data(output);
208                                 var node = pa.get_root();
209
210                                 if (node.get_node_type () != Json.NodeType.OBJECT) {
211                                         BuilderApplication.showSpinner(false);
212                                         return;
213                                 }
214                                 var ret = node.get_object ();   
215                                 //CompileError.parseCompileResults(this,ret);
216                                 BuilderApplication.showSpinner(false);
217                                 
218                         
219                                 
220                                 
221                                 
222                         } catch (GLib.Error e) {
223                                 GLib.debug("parsing output got error %s", e.message);
224                                 BuilderApplication.showSpinner(false);
225                                 return;
226                                 
227                         }
228                         if (this.requestType == ValaCompileRequestType.RUN) {
229                                 this.execResult();
230                         }
231                 }
232                  
233                 public void onOutput(string line)
234                 {
235                         // pass it to UI?
236                         
237                 }
238                 public int totalErrors(string type, JsRender.JsRender? file=null) 
239                 {
240                         var ar = this.errorByType.get(type);
241                         if (ar == null) {
242                                 GLib.debug("by type has no eroros %s", type);
243                                 return 0;
244                         }
245                         
246                         
247                         var ret =0;
248                         
249                         for(var i =0 ;i< ar.get_n_items();i++) {
250                                 var ce = (CompileError) ar.get_item(i);
251                                 if (file == null) {
252                                         ret += (int)ce.lines.get_n_items();
253                                         GLib.debug("got lines type has no eroros %s", type);
254                                         continue;
255                                 }
256                                 
257                                 
258                                 if (ce.file.path == file.path) {
259                                         ret += (int)ce.lines.get_n_items();
260                                 }
261                         }
262                         return ret;
263                 }
264                 
265                 public void runJavascript( )
266                 {
267                         //this.queue = queue;
268                  
269                         var contents = this.alt_code == "" ? this.file.toSourceCode() : this.generateTempContents();
270                         
271                         Javascript.singleton().validate(contents, this.file );
272                         
273                         
274                          
275                         BuilderApplication.showSpinner(false);
276                         BuilderApplication.updateCompileResults();
277                         
278                         //this.queue.onCompileComplete(this);
279                                 
280                          
281                   // see pack file (from palete/palete..palete_palete_javascriptHasCompressionErrors.)
282                   
283                 }
284                 public void killChildren(int pid)
285                 {
286                         if (pid < 1) {
287                                 return;
288                         }
289                         var cn = "/proc/%d/task/%d/children".printf(pid,pid);
290                         if (!FileUtils.test(cn, GLib.FileTest.EXISTS)) {
291                                 GLib.debug("%s doesnt exist - killing %d", cn, pid);
292                                 Posix.kill(pid, 9);
293                                 return;
294                         }
295                         string cpids = "";
296                         try {
297                                 FileUtils.get_contents(cn, out cpids);
298                         
299
300                                 if (cpids.length > 0) {
301                                         this.killChildren(int.parse(cpids));
302                                 }
303
304                         } catch (GLib.FileError e) {
305                                 // skip
306                         }
307                         GLib.debug("killing %d", pid);  
308                         Posix.kill(pid, 9);
309                 }
310                 
311                 int terminal_pid = 0;
312                 public void execResult()
313                 {
314                                 
315                         this.killChildren(this.terminal_pid);
316                         this.terminal_pid = 0;
317                           
318                         var exe = this.target();
319                         var pr = (Project.Gtk) this.file.project;
320                         var cg =  pr.compilegroups.get(exe);
321                         
322                         if (!GLib.FileUtils.test(exe, GLib.FileTest.EXISTS)) {
323                                 print("Missing output file: %s\n",exe);
324                                 return;
325                         }
326                         var gdb_cfg= pr.path + "/build/.gdb-script";
327                         if (!GLib.FileUtils.test(gdb_cfg, GLib.FileTest.EXISTS)) {
328                                 pr.writeFile("build/.gdb-script", "set debuginfod enabled off\nr");
329                         }
330                         
331                         
332                         
333                         string[] args = "/usr/bin/gnome-terminal --disable-factory --wait -- /usr/bin/gdb -x".split(" ");
334
335                         args+= gdb_cfg;
336  
337                         args += exe;
338                         if (cg.execute_args.length > 0) {
339                                 args+= "--args";
340                                 var aa = cg.execute_args.split(" ");
341                                 for (var i =0; i < aa.length; i++) {
342                                         args += aa[i];
343                                 }
344                         }
345
346                   
347                     
348                     // should be home directory...
349                     
350                     
351                     try {
352                     
353                         var exec = new Spawn(pr.path , args);
354                         exec.env = GLib.Environ.get();
355                          
356                         exec.detach = true;
357                                 exec.run(); 
358
359                                 this.terminal_pid = exec.pid;
360                                 GLib.debug("Child PID = %d", this.terminal_pid);
361                                 
362                     } catch(GLib.Error e) {
363                                 GLib.debug("Failed to spawn: %s", e.message);
364                                 return;
365                         }
366                         
367                 }
368                 
369         } 
370                 
371                 
372                 
373 }
374
375