Extended the builder with an index file generator for PHP class- and function-names.
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / phpeditor / PHPSyntaxParserThread.java
1 package net.sourceforge.phpeclipse.phpeditor;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5
6 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
7
8 import org.eclipse.core.resources.IFile;
9 import org.eclipse.core.resources.IMarker;
10 import org.eclipse.core.runtime.CoreException;
11 import org.eclipse.jface.preference.IPreferenceStore;
12 import org.eclipse.jface.text.source.ISourceViewer;
13 import org.eclipse.ui.IEditorInput;
14 import org.eclipse.ui.IFileEditorInput;
15 import org.eclipse.ui.editors.text.TextEditor;
16
17 import test.PHPParserManager;
18 import test.PHPParserSuperclass;
19
20
21 public class PHPSyntaxParserThread extends Thread {
22   private static String[] EXTENSIONS = { ".php", ".php3", ".php4", ".inc", ".phtml" };
23
24         private String text = "";
25         private String previousText = "";
26
27         private boolean stopValidation = false;
28         private boolean validationTerminated = false;
29         private boolean isActive = false;
30
31         private TextEditor fTextEditor;
32         private ISourceViewer fSourceViewer;
33
34         private int previousHashCode = 0;
35         // Defaults
36         private int validationInterval = 2000; //millis
37         private int waitForTermination = 400; // millis
38         private int maxErrorsShown = 10;
39
40         public PHPSyntaxParserThread(
41                 TextEditor textEditor,
42                 ISourceViewer viewer) {
43                 super();
44                 fTextEditor = textEditor;
45                 fSourceViewer = viewer;
46         }
47
48         public void setText(String text) {
49                 if (!isActive)
50                         this.text = text;
51         }
52
53         public void setText(String text, boolean forceUpdate) {
54                 if (!isActive) {
55                         this.text = text;
56                 }
57
58                 if (forceUpdate) {
59                         this.previousText = "";
60                         this.previousHashCode = 0;
61                 }
62         }
63
64         public String getText() {
65                 return text;
66         }
67
68         public void setInterval(int millis) {
69                 this.validationInterval = millis;
70         }
71
72         public int getInterval() {
73                 return validationInterval;
74         }
75
76         public void setErrorsShown(int number) {
77                 this.maxErrorsShown = number;
78         }
79
80         public int getErrorsShown() {
81                 return maxErrorsShown;
82         }
83
84         public void dispose() {
85                 this.stopValidation = true;
86
87                 if (validationTerminated == false) {
88
89                         try {
90                                 Thread.sleep(waitForTermination);
91                         } catch (Exception e) {
92                         }
93                 }
94         }
95
96         public void run() {
97                 while (stopValidation == false) {
98                         try {
99
100                                 this.isActive = true;
101                                 boolean ret = this.validateSyntax();
102
103                                 this.previousText = this.text;
104                                 this.isActive = false;
105
106                                 Thread.sleep(validationInterval);
107
108                         } catch (Exception e) {
109                                 e.printStackTrace();
110                         }
111                 }
112
113                 this.validationTerminated = true;
114         }
115
116         public boolean validateSyntax() {
117
118     boolean phpFlag = false;
119     try {
120       IFile fileToParse = getPHPFile(fTextEditor.getEditorInput());
121       if (fileToParse == null) {
122         // should never happen
123         System.err.println("Error : no file in the editor");
124         // should throw an exception
125         return false;
126       }
127       String name = fileToParse.getName();
128       for (int i = 0; i<EXTENSIONS.length; i++) {
129         if (name.endsWith(EXTENSIONS[i])) {
130           phpFlag = true;  // php file extension
131           break;
132         }
133       }
134       if (phpFlag) {
135         IPreferenceStore store = PHPeclipsePlugin.getDefault().getPreferenceStore();
136         if (store.getString(PHPeclipsePlugin.PHP_PARSER_DEFAULT).equals(PHPeclipsePlugin.PHP_INTERNAL_PARSER)) {
137           // first delete all the previous markers
138           fileToParse.deleteMarkers(IMarker.PROBLEM, false, 0);
139
140           try {
141             InputStream iStream = fileToParse.getContents();
142             //        int c = iStream.read();
143             parse(fileToParse, iStream);
144             iStream.close();
145           } catch (IOException e) {
146           }
147         } else {
148           PHPParserSuperclass.phpExternalParse(fileToParse);
149         }
150       }
151     } catch (CoreException e) {
152     }
153
154  
155 //
156 //              Process proc = null;
157 //
158 //              if (this.previousText.equals(this.text)) {
159 //                      return true;
160 //              }
161 //
162 //              try {
163 //                      IEditorInput input = fTextEditor.getEditorInput();
164 //                      IResource resource =
165 //                              (IResource) ((IAdaptable) input).getAdapter(IResource.class);
166 //
167 //                      // Write output file
168 //                      FileOutputStream fos = new FileOutputStream(new File(tmpFileName));
169 //                      fos.write(text.getBytes());
170 //                      fos.flush();
171 //                      fos.close();
172 //
173 //                      proc =
174 //                              Runtime.getRuntime().exec(
175 //                                      PerlEditorPlugin
176 //                                              .getDefault()
177 //                                              .getExecutablePreference()
178 //                                              .trim()
179 //                                              + " "
180 //                                              + "-I"
181 //                                              + ((IFileEditorInput) this.fTextEditor.getEditorInput())
182 //                                                      .getFile()
183 //                                                      .getLocation()
184 //                                                      .makeAbsolute()
185 //                                                      .removeLastSegments(1)
186 //                                              + " "
187 //                                              + PERL_CMD_EXT
188 //                                              + " "
189 //                                              + tmpFileName);
190 //
191 //                      InputStream in = proc.getErrorStream();
192 //
193 //                      StringBuffer content = new StringBuffer();
194 //
195 //                      byte[] buffer = new byte[1];
196 //
197 //                      int read;
198 //                      while ((read = in.read(buffer)) > 0) {
199 //                              content.append(new String(buffer));
200 //                      }
201 //                      in.close();
202 //
203 //                      //jjjjjjj
204 //                      // DEBUG start
205 //                      System.out.println("-----------------------------------------");
206 //                      System.out.println("           OUTPUT");
207 //                      System.out.println("-----------------------------------------");
208 //                      System.out.println(content);
209 //                      System.out.println("-----------------------------------------");
210 //                      // DEBUG END
211 //
212 //                      String line = null;
213 //                      List lines = new ArrayList();
214 //                      int index;
215 //
216 //                      // Compare checksums
217 //                      int hashCode = content.toString().hashCode();
218 //
219 //                      if (previousHashCode == hashCode) {
220 //
221 //                              return true;
222 //                      }
223 //
224 //                      previousHashCode = hashCode;
225 //
226 //                      StringTokenizer st = new StringTokenizer(content.toString(), "\n");
227 //
228 //                      int lineCount = 0;
229 //
230 //                      while (st.hasMoreTokens()) {
231 //                              line = st.nextToken();
232 //                              if (line.indexOf("\r") != -1) {
233 //                                      line = line.substring(0, line.indexOf("\r"));
234 //                              }
235 //
236 //                              lines.add(line);
237 //                              if (++lineCount >= maxErrorsShown) {
238 //                                      break;
239 //                              }
240 //
241 //                      }
242 //
243 //                      //Delete markers
244 //                      resource.deleteMarkers(IMarker.PROBLEM, true, 1);
245 //
246 //                      // Markers have to be added in reverse order
247 //                      // Otherwise lower line number will appear at the end of the list
248 //                      for (int i = lines.size() - 1; i >= 0; i--) {
249 //                              line = (String) lines.get(i);
250 //
251 //                              // If error message is not from temporary file, skip
252 //                              if (line.indexOf(tmpFileName) == -1) {
253 //                                      continue;
254 //                              }
255 //
256 //                              // Delete filename from error message
257 //                              StringBuffer lineSb = new StringBuffer(line);
258 //                              replace(lineSb, tmpFileName + " ", "", true);
259 //                              line = lineSb.toString();
260 //
261 //                              if ((index = line.indexOf(PERL_ERROR_INDICATOR)) != -1) {
262 //
263 //                                      // truncatedLIne is the stripped error-line up to the next " " after the line number if present
264 //                                      // To avoid cluttering with other "." and "," which might occur in the error message
265 //                                      String truncatedLine = line;
266 //                                      if (truncatedLine
267 //                                              .indexOf(" ", index + PERL_ERROR_INDICATOR.length() + 1)
268 //                                              != -1) {
269 //                                              truncatedLine =
270 //                                                      truncatedLine.substring(
271 //                                                              0,
272 //                                                              truncatedLine.indexOf(
273 //                                                                      " ",
274 //                                                                      index + PERL_ERROR_INDICATOR.length() + 1));
275 //                                      }
276 //
277 //                                      int endIndex;
278 //                                      if ((endIndex = truncatedLine.indexOf(".", index)) == -1) {
279 //                                              endIndex = truncatedLine.indexOf(",", index);
280 //                                      }
281 //
282 //                                      if (endIndex == -1) {
283 //                                              continue;
284 //                                      }
285 //
286 //                                      String lineNr =
287 //                                              truncatedLine.substring(
288 //                                                      index + PERL_ERROR_INDICATOR.length(),
289 //                                                      endIndex);
290 //
291 //                                      // If there is an addition to the error message
292 //                                      if (i + 1 < lines.size()) {
293 //                                              if (((String) lines.get(i + 1)).startsWith(" ")) {
294 //                                                      line += " " + (String) lines.get(i + 1);
295 //                                              }
296 //                                      }
297 //
298 //                                      IMarker marker = resource.createMarker(IMarker.PROBLEM);
299 //
300 //                                      // Check if it's a warning
301 //                                      boolean isWarning = false;
302 //
303 //                                      for (int x = 0; x < WARNING_STRINGS.length; x++) {
304 //                                              if (truncatedLine.indexOf(WARNING_STRINGS[x]) != -1) {
305 //                                                      isWarning = true;
306 //                                              }
307 //                                      }
308 //
309 //                                      if (isWarning) {
310 //                                              marker.setAttribute(
311 //                                                      IMarker.SEVERITY,
312 //                                                      IMarker.SEVERITY_WARNING);
313 //                                      } else {
314 //                                              marker.setAttribute(
315 //                                                      IMarker.SEVERITY,
316 //                                                      IMarker.SEVERITY_ERROR);
317 //                                      }
318 //
319 //                                      marker.setAttribute(IMarker.MESSAGE, line);
320 //
321 //                                      marker.setAttribute(
322 //                                              IMarker.LINE_NUMBER,
323 //                                              Integer.parseInt(lineNr));
324 //
325 //                                      Position pos =
326 //                                              new Position(
327 //                                                      fSourceViewer.getDocument().getLineOffset(
328 //                                                              Integer.parseInt(lineNr) - 1));
329 //                                      fSourceViewer.getAnnotationModel().addAnnotation(
330 //                                              new MarkerAnnotation(marker),
331 //                                              pos);
332 //
333 //                              }
334 //                      }
335 //
336 //              } catch (Exception e) {
337 //                      e.printStackTrace();
338 //                      if (proc != null) {
339 //                              killProcess(proc);
340 //                      }
341 //                      return false;
342 //              } finally {
343 //                      try {
344 //                              //                              Delete tmp file
345 //                              new File(tmpFileName).delete();
346 //                      } catch (Exception ex) {
347 //                              ex.printStackTrace();
348 //                      }
349 //              }
350
351                 return true;
352
353         }
354
355   /**
356     * Finds the file that's currently opened in the PHP Text Editor
357     */
358    protected IFile getPHPFile(IEditorInput editorInput) {
359      if (editorInput instanceof IFileEditorInput)
360        return ((IFileEditorInput) editorInput).getFile();
361
362      return null;
363    }
364     
365    protected void parse(IFile fileToParse, InputStream iStream) {
366
367      StringBuffer buf = new StringBuffer();
368      int c0;
369      try {
370        while ((c0 = iStream.read()) != (-1)) {
371          buf.append((char) c0);
372        }
373      } catch (IOException e) {
374        return;
375      }
376      String input = buf.toString();
377
378      PHPParserSuperclass parser = PHPParserManager.getParser(fileToParse);
379      try {
380        parser.parse(input);
381      } catch (CoreException e) {
382      }
383    }
384    
385         private void killProcess(Process proc) {
386                 while (true) {
387                         try {
388                                 proc.destroy();
389                                 proc.exitValue();
390                         } catch (Exception ex) {
391
392                                 continue;
393                         }
394                         break;
395                 }
396         }
397
398         // Replaces all instances of the String o with the String n in the
399         // StringBuffer orig if all is true, or only the first instance if all is false.
400         private static void replace(
401                 StringBuffer orig,
402                 String o,
403                 String n,
404                 boolean all) {
405                 if (orig == null || o == null || o.length() == 0 || n == null)
406                         throw new IllegalArgumentException("Null or zero-length String");
407
408                 int i = 0;
409
410                 while (i + o.length() <= orig.length()) {
411                         if (orig.substring(i, i + o.length()).equals(o)) {
412                                 orig.replace(i, i + o.length(), n);
413                                 if (!all)
414                                         break;
415                                 else
416                                         i += n.length();
417                         } else
418                                 i++;
419                 }
420         }
421 }