fix #7968 - language server support for syntax check and completion
[roobuilder] / src / Palete / ValaCompileQueue.vala
1
2 /**
3         only one queue exists for the whole program
4 */
5 namespace Palete {
6         
7         public class ValaCompileQueueX : Object 
8         {
9         
10                 ValaCompileRequest? next_request = null;
11                 ValaCompileRequest? cur_request = null;
12                 ValaCompileRequest? last_request = null;
13                 
14                  
15  
16                 
17                 int countdown_start = 5;
18                 int countdown = -1;
19                 int timeout = 0;
20                 uint countdown_running = 0;
21                 
22                 int terminal_pid = 0;
23                 
24                 
25                 
26                 public ValaCompileQueueX()
27                 {
28                         //start timeout for compiler.
29                         
30                 }
31                 
32                 public void addFileX(  ValaCompileRequestType reqtype, JsRender.JsRender file , string alt_code, bool force) 
33                 {
34                         var add = new ValaCompileRequest(
35                                 reqtype,
36                                 file,
37                                 null,
38                                 null,
39                                 alt_code
40                         );
41  
42
43                         if (file.project.xtype == "Gtk" && file.targetName().has_suffix(".vala")) {
44                         
45                                 
46                                 this.add(add , force);
47                         }
48                         if (file.project.xtype == "Roo"  && file.targetName().has_suffix(".js")) {
49                                 this.next_request = null;
50                                 this.cur_request = add;
51                                 add.runJavascript(this); 
52                          }
53                 }
54                 
55                 
56                 public void addPropX( ValaCompileRequestType requestType,
57                         JsRender.JsRender file,
58                         JsRender.Node node,
59                         JsRender.NodeProp prop,
60                         string alt_code
61                 ) 
62                 {
63                         if (prop.name == "xns" || prop.name == "xtype") {
64                                 return ;
65                         }
66                         var add = new ValaCompileRequest(
67                                 requestType,
68                                 file,
69                                 node,
70                                 prop,
71                                 alt_code
72                         );      
73                  
74                         if (file.project.xtype == "Gtk")  {
75                                 this.add(add , false); // delayed?
76                         }
77                         if (file.project.xtype == "Roo" )  {
78                                 this.next_request = null;
79                                 this.cur_request = add;
80                                 add.runJavascript(this); 
81                         }        
82                 }
83                 void add(ValaCompileRequest req, bool force)
84                 {
85                         GLib.debug("Add compile request  to queue %s", req.file.path);
86                         if (this.next_request != null && this.next_request.eq(req)) {
87                                 this.countdown = this.last_request == null || force ? 1 : this.countdown_start;                 
88  
89                                 if (this.countdown_running < 1) {
90                                         this.startCountdown();
91                                 }
92                                 return;
93                         }
94                         if (this.cur_request != null && this.cur_request.eq(req)) { // ingore
95                                 GLib.debug("Ingore - its' running Add compile request  to queue %s", req.file.path);                    
96                                 return;
97                         }
98                         if (this.last_request != null && this.last_request.eq(req)) { // ingore
99                                 GLib.debug("Ingore - its same as last request %s", req.file.path);                                              
100                                 return;
101                         }
102                         this.next_request = req;
103                         // quick if no previous
104                         this.countdown = this.last_request == null || force ? 1 : this.countdown_start;
105                         if (this.countdown_running < 1) {
106                                 this.startCountdown();
107                         }
108                 
109                 }
110         
111                 public void startCountdown()
112                 {
113                         this.countdown_running = GLib.Timeout.add_seconds(1, () => {
114                                 if (this.next_request == null && this.cur_request == null) {
115                                         this.countdown_running = 0;
116                                         return false;
117                                 }
118                                 this.countdown--;
119                                  // 60 sedonds
120                                 if (this.cur_request == null) {
121                                         this.timeout = 0;
122                                 }
123                                 if (this.cur_request != null) {
124                                 
125                                         this.timeout--;
126                                  GLib.debug("Timeout running %d", this.timeout);
127                                         if (this.timeout < 1) {
128                                                  GLib.debug("Timeout canceling %s", this.cur_request.file.path);
129                                                 this.cur_request.cancel();
130                                                 this.cur_request = null;
131                                         }
132                                 }
133                                  
134                                 if (this.countdown < 1) {
135                                         this.run();
136                                         this.countdown_running = 0;
137                                         return false;
138                                 }
139                                  
140                                 return true; // keep going.
141                         });
142                         
143                 
144                 }
145         
146                 
147                 // called on each tick/timeout
148                 // not called if compiler is running..
149                 void run()
150                 {
151                         this.timeout = 30;
152                         var req = this.next_request;
153                         this.next_request = null;
154                         this.cur_request = req;
155                          
156                         
157                         if (!req.run(this)) {
158                                 GLib.debug("run failed- give up on this one - should we show a problem??");
159                                 this.onCompileFail();
160                                 return;
161                         } 
162                         this.showSpinner(true); 
163                          
164                 
165                 }
166                 public void onCompileFail()
167                 {
168                         this.cur_request = null;
169                         this.showSpinner(false);
170                 }
171                 
172                 public void onCompileComplete(ValaCompileRequest req)
173                 {
174                         this.cur_request = null;
175                         //req.file.project.last_request = req; // technically it should update compile group.
176                         this.last_request = req;
177                         this.showSpinner(false);
178                         // update errors
179                         BuilderApplication.updateCompileResults();
180                 }
181                 
182                 public void onCompilerOutput(   string str )
183                 {
184                         // send output to all windows (of this project?)
185                         
186                 }
187                 public void showSpinner(bool state)
188                 {
189                         foreach (var win in BuilderApplication.windows) {
190                                 if (state) {
191                                         win.statusbar_compile_spinner.start();
192                                 }  else {
193                                         win.statusbar_compile_spinner.stop();
194                                 }
195                         }
196                 }
197                 
198                 // handle execution of result..-------
199                 
200                 public void killChildren(int pid)
201                 {
202                         if (pid < 1) {
203                                 return;
204                         }
205                         var cn = "/proc/%d/task/%d/children".printf(pid,pid);
206                         if (!FileUtils.test(cn, GLib.FileTest.EXISTS)) {
207                                 GLib.debug("%s doesnt exist - killing %d", cn, pid);
208                                 Posix.kill(pid, 9);
209                                 return;
210                         }
211                         string cpids = "";
212                         try {
213                                 FileUtils.get_contents(cn, out cpids);
214                         
215
216                                 if (cpids.length > 0) {
217                                         this.killChildren(int.parse(cpids));
218                                 }
219
220                         } catch (GLib.FileError e) {
221                                 // skip
222                         }
223                         GLib.debug("killing %d", pid);  
224                         Posix.kill(pid, 9);
225                 }
226                 
227                 
228                 public void execResult(ValaCompileRequest req)
229                 {
230                                 
231                         this.killChildren(this.terminal_pid);
232                         this.terminal_pid = 0;
233                           
234                         var exe = req.target();
235                         var pr = (Project.Gtk) req.file.project;
236                         var cg =  pr.compilegroups.get(exe);
237                         
238                         if (!GLib.FileUtils.test(exe, GLib.FileTest.EXISTS)) {
239                                 print("Missing output file: %s\n",exe);
240                                 return;
241                         }
242                         var gdb_cfg= pr.path + "/build/.gdb-script";
243                         if (!GLib.FileUtils.test(gdb_cfg, GLib.FileTest.EXISTS)) {
244                                 pr.writeFile("build/.gdb-script", "set debuginfod enabled off\nr");
245                         }
246                         
247                         
248                         
249                         string[] args = "/usr/bin/gnome-terminal --disable-factory --wait -- /usr/bin/gdb -x".split(" ");
250
251                         args+= gdb_cfg;
252  
253                         args += exe;
254                         if (cg.execute_args.length > 0) {
255                                 args+= "--args";
256                                 var aa = cg.execute_args.split(" ");
257                                 for (var i =0; i < aa.length; i++) {
258                                         args += aa[i];
259                                 }
260                         }
261
262                   
263                     
264                     // should be home directory...
265                     
266                     
267                     try {
268                     
269                         var exec = new Spawn(pr.path , args);
270                         exec.env = GLib.Environ.get();
271                          
272                         exec.detach = true;
273                                 exec.run(); 
274
275                                 this.terminal_pid = exec.pid;
276                                 GLib.debug("Child PID = %d", this.terminal_pid);
277                                 
278                     } catch(GLib.Error e) {
279                                 GLib.debug("Failed to spawn: %s", e.message);
280                                 return;
281                         }
282                         
283                 }
284                 
285                 
286                 
287                 
288         }
289         
290 }