1 package net.sourceforge.phpeclipse.phpeditor;
3 import java.io.IOException;
4 import java.io.InputStream;
6 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
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;
17 import test.PHPParserManager;
18 import test.PHPParserSuperclass;
21 public class PHPSyntaxParserThread extends Thread {
22 private static String[] EXTENSIONS = { ".php", ".php3", ".php4", ".inc", ".phtml" };
24 private String text = "";
25 private String previousText = "";
27 private boolean stopValidation = false;
28 private boolean validationTerminated = false;
29 private boolean isActive = false;
31 private TextEditor fTextEditor;
32 private ISourceViewer fSourceViewer;
34 private int previousHashCode = 0;
36 private int validationInterval = 2000; //millis
37 private int waitForTermination = 400; // millis
38 private int maxErrorsShown = 10;
40 public PHPSyntaxParserThread(
41 TextEditor textEditor,
42 ISourceViewer viewer) {
44 fTextEditor = textEditor;
45 fSourceViewer = viewer;
48 public void setText(String text) {
53 public void setText(String text, boolean forceUpdate) {
59 this.previousText = "";
60 this.previousHashCode = 0;
64 public String getText() {
68 public void setInterval(int millis) {
69 this.validationInterval = millis;
72 public int getInterval() {
73 return validationInterval;
76 public void setErrorsShown(int number) {
77 this.maxErrorsShown = number;
80 public int getErrorsShown() {
81 return maxErrorsShown;
84 public void dispose() {
85 this.stopValidation = true;
87 if (validationTerminated == false) {
90 Thread.sleep(waitForTermination);
91 } catch (Exception e) {
97 while (stopValidation == false) {
100 this.isActive = true;
101 boolean ret = this.validateSyntax();
103 this.previousText = this.text;
104 this.isActive = false;
106 Thread.sleep(validationInterval);
108 } catch (Exception e) {
113 this.validationTerminated = true;
116 public boolean validateSyntax() {
118 boolean phpFlag = false;
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
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
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);
141 InputStream iStream = fileToParse.getContents();
142 // int c = iStream.read();
143 parse(fileToParse, iStream);
145 } catch (IOException e) {
148 PHPParserSuperclass.phpExternalParse(fileToParse);
151 } catch (CoreException e) {
156 // Process proc = null;
158 // if (this.previousText.equals(this.text)) {
163 // IEditorInput input = fTextEditor.getEditorInput();
164 // IResource resource =
165 // (IResource) ((IAdaptable) input).getAdapter(IResource.class);
167 // // Write output file
168 // FileOutputStream fos = new FileOutputStream(new File(tmpFileName));
169 // fos.write(text.getBytes());
174 // Runtime.getRuntime().exec(
177 // .getExecutablePreference()
181 // + ((IFileEditorInput) this.fTextEditor.getEditorInput())
185 // .removeLastSegments(1)
191 // InputStream in = proc.getErrorStream();
193 // StringBuffer content = new StringBuffer();
195 // byte[] buffer = new byte[1];
198 // while ((read = in.read(buffer)) > 0) {
199 // content.append(new String(buffer));
205 // System.out.println("-----------------------------------------");
206 // System.out.println(" OUTPUT");
207 // System.out.println("-----------------------------------------");
208 // System.out.println(content);
209 // System.out.println("-----------------------------------------");
212 // String line = null;
213 // List lines = new ArrayList();
216 // // Compare checksums
217 // int hashCode = content.toString().hashCode();
219 // if (previousHashCode == hashCode) {
224 // previousHashCode = hashCode;
226 // StringTokenizer st = new StringTokenizer(content.toString(), "\n");
228 // int lineCount = 0;
230 // while (st.hasMoreTokens()) {
231 // line = st.nextToken();
232 // if (line.indexOf("\r") != -1) {
233 // line = line.substring(0, line.indexOf("\r"));
237 // if (++lineCount >= maxErrorsShown) {
244 // resource.deleteMarkers(IMarker.PROBLEM, true, 1);
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);
251 // // If error message is not from temporary file, skip
252 // if (line.indexOf(tmpFileName) == -1) {
256 // // Delete filename from error message
257 // StringBuffer lineSb = new StringBuffer(line);
258 // replace(lineSb, tmpFileName + " ", "", true);
259 // line = lineSb.toString();
261 // if ((index = line.indexOf(PERL_ERROR_INDICATOR)) != -1) {
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;
267 // .indexOf(" ", index + PERL_ERROR_INDICATOR.length() + 1)
270 // truncatedLine.substring(
272 // truncatedLine.indexOf(
274 // index + PERL_ERROR_INDICATOR.length() + 1));
278 // if ((endIndex = truncatedLine.indexOf(".", index)) == -1) {
279 // endIndex = truncatedLine.indexOf(",", index);
282 // if (endIndex == -1) {
287 // truncatedLine.substring(
288 // index + PERL_ERROR_INDICATOR.length(),
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);
298 // IMarker marker = resource.createMarker(IMarker.PROBLEM);
300 // // Check if it's a warning
301 // boolean isWarning = false;
303 // for (int x = 0; x < WARNING_STRINGS.length; x++) {
304 // if (truncatedLine.indexOf(WARNING_STRINGS[x]) != -1) {
310 // marker.setAttribute(
312 // IMarker.SEVERITY_WARNING);
314 // marker.setAttribute(
316 // IMarker.SEVERITY_ERROR);
319 // marker.setAttribute(IMarker.MESSAGE, line);
321 // marker.setAttribute(
322 // IMarker.LINE_NUMBER,
323 // Integer.parseInt(lineNr));
327 // fSourceViewer.getDocument().getLineOffset(
328 // Integer.parseInt(lineNr) - 1));
329 // fSourceViewer.getAnnotationModel().addAnnotation(
330 // new MarkerAnnotation(marker),
336 // } catch (Exception e) {
337 // e.printStackTrace();
338 // if (proc != null) {
339 // killProcess(proc);
344 // // Delete tmp file
345 // new File(tmpFileName).delete();
346 // } catch (Exception ex) {
347 // ex.printStackTrace();
356 * Finds the file that's currently opened in the PHP Text Editor
358 protected IFile getPHPFile(IEditorInput editorInput) {
359 if (editorInput instanceof IFileEditorInput)
360 return ((IFileEditorInput) editorInput).getFile();
365 protected void parse(IFile fileToParse, InputStream iStream) {
367 StringBuffer buf = new StringBuffer();
370 while ((c0 = iStream.read()) != (-1)) {
371 buf.append((char) c0);
373 } catch (IOException e) {
376 String input = buf.toString();
378 PHPParserSuperclass parser = PHPParserManager.getParser(fileToParse);
381 } catch (CoreException e) {
385 private void killProcess(Process proc) {
390 } catch (Exception ex) {
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(
405 if (orig == null || o == null || o.length() == 0 || n == null)
406 throw new IllegalArgumentException("Null or zero-length String");
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);